diff options
64 files changed, 2367 insertions, 229 deletions
| @@ -39,3 +39,6 @@     digital signature algorithm, and Poly1305 MAC algorithm, all by     Daniel J. Bernstein (public domain)<br>     http://cr.yp.to/ + + * MiniUPNPC by Thomas Bernard [BSD] +   http://miniupnp.free.fr diff --git a/controller/SqliteNetworkController.cpp b/controller/SqliteNetworkController.cpp index 700b3561..50be5b34 100644 --- a/controller/SqliteNetworkController.cpp +++ b/controller/SqliteNetworkController.cpp @@ -64,6 +64,10 @@  // API version reported via JSON control plane  #define ZT_NETCONF_CONTROLLER_API_VERSION 1 +// Drop requests for a given peer and network ID that occur more frequently +// than this (ms). +#define ZT_NETCONF_MIN_REQUEST_PERIOD 1000 +  namespace ZeroTier {  namespace { @@ -142,6 +146,7 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :  		// Prepare statement will fail if Config table doesn't exist, which means our DB  		// needs to be initialized.  		if (sqlite3_exec(_db,ZT_NETCONF_SCHEMA_SQL"INSERT INTO Config (k,v) VALUES ('schemaVersion',"ZT_NETCONF_SQLITE_SCHEMA_VERSION_STR");",0,0,0) != SQLITE_OK) { +			//printf("%s\n",sqlite3_errmsg(_db));  			sqlite3_close(_db);  			throw std::runtime_error("SqliteNetworkController cannot initialize database and/or insert schemaVersion into Config table");  		} @@ -199,16 +204,21 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :  			||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)  			/* Gateway */ -			||(sqlite3_prepare_v2(_db,"SELECT ip,ipVersion,metric FROM Gateway WHERE networkId = ? ORDER BY metric ASC",-1,&_sGetGateways,(const char **)0) != SQLITE_OK) +			||(sqlite3_prepare_v2(_db,"SELECT \"ip\",ipVersion,metric FROM Gateway WHERE networkId = ? ORDER BY metric ASC",-1,&_sGetGateways,(const char **)0) != SQLITE_OK)  			||(sqlite3_prepare_v2(_db,"DELETE FROM Gateway WHERE networkId = ?",-1,&_sDeleteGateways,(const char **)0) != SQLITE_OK) -			||(sqlite3_prepare_v2(_db,"INSERT INTO Gateway (networkId,ip,ipVersion,metric) VALUES (?,?,?,?)",-1,&_sCreateGateway,(const char **)0) != SQLITE_OK) +			||(sqlite3_prepare_v2(_db,"INSERT INTO Gateway (networkId,\"ip\",ipVersion,metric) VALUES (?,?,?,?)",-1,&_sCreateGateway,(const char **)0) != SQLITE_OK) + +			/* Log */ +			||(sqlite3_prepare_v2(_db,"INSERT INTO \"Log\" (networkId,nodeId,\"ts\",\"authorized\",\"version\",fromAddr) VALUES (?,?,?,?,?,?)",-1,&_sPutLog,(const char **)0) != SQLITE_OK) +			||(sqlite3_prepare_v2(_db,"SELECT \"ts\",\"authorized\",\"version\",fromAddr FROM \"Log\" WHERE networkId = ? AND nodeId = ? AND \"ts\" >= ? ORDER BY \"ts\" ASC",-1,&_sGetMemberLog,(const char **)0) != SQLITE_OK) +			||(sqlite3_prepare_v2(_db,"SELECT \"ts\",\"authorized\",\"version\",fromAddr FROM \"Log\" WHERE networkId = ? AND nodeId = ? ORDER BY \"ts\" DESC LIMIT 10",-1,&_sGetRecentMemberLog,(const char **)0) != SQLITE_OK)  			/* Config */  			||(sqlite3_prepare_v2(_db,"SELECT \"v\" FROM \"Config\" WHERE \"k\" = ?",-1,&_sGetConfig,(const char **)0) != SQLITE_OK)  			||(sqlite3_prepare_v2(_db,"INSERT OR REPLACE INTO \"Config\" (\"k\",\"v\") VALUES (?,?)",-1,&_sSetConfig,(const char **)0) != SQLITE_OK)  		 ) { -		//printf("!!! %s\n",sqlite3_errmsg(_db)); +		//printf("%s\n",sqlite3_errmsg(_db));  		sqlite3_close(_db);  		throw std::runtime_error("SqliteNetworkController unable to initialize one or more prepared statements");  	} @@ -283,12 +293,21 @@ SqliteNetworkController::~SqliteNetworkController()  		sqlite3_finalize(_sIncrementMemberRevisionCounter);  		sqlite3_finalize(_sGetConfig);  		sqlite3_finalize(_sSetConfig); +		sqlite3_finalize(_sPutLog); +		sqlite3_finalize(_sGetMemberLog); +		sqlite3_finalize(_sGetRecentMemberLog);  		sqlite3_close(_db);  	}  }  NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(const InetAddress &fromAddr,const Identity &signingId,const Identity &identity,uint64_t nwid,const Dictionary &metaData,uint64_t haveRevision,Dictionary &netconf)  { +	// Decode some stuff from metaData +	const unsigned int clientMajorVersion = (unsigned int)metaData.getHexUInt(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,0); +	const unsigned int clientMinorVersion = (unsigned int)metaData.getHexUInt(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,0); +	const unsigned int clientRevision = (unsigned int)metaData.getHexUInt(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,0); +	const bool clientIs104 = (Utils::compareVersion(clientMajorVersion,clientMinorVersion,clientRevision,1,0,4) >= 0); +  	Mutex::Lock _l(_lock);  	// Note: we can't reuse prepared statements that return const char * pointers without @@ -303,6 +322,15 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co  		return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR;  	} +	// Check rate limit + +	{ +		uint64_t &lrt = _lastRequestTime[std::pair<Address,uint64_t>(identity.address(),nwid)]; +		uint64_t lrt2 = lrt; +		if (((lrt = OSUtils::now()) - lrt2) <= ZT_NETCONF_MIN_REQUEST_PERIOD) +			return NetworkController::NETCONF_QUERY_IGNORE; +	} +  	NetworkRecord network;  	memset(&network,0,sizeof(network));  	Utils::snprintf(network.id,sizeof(network.id),"%.16llx",(unsigned long long)nwid); @@ -387,18 +415,35 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co  		sqlite3_step(_sIncrementMemberRevisionCounter);  	} +	// Add log entry +	{ +		char ver[16]; +		std::string fa; +		if (fromAddr) { +			fa = fromAddr.toString(); +			if (fa.length() > 64) +				fa = fa.substr(0,64); +		} +		sqlite3_reset(_sPutLog); +		sqlite3_bind_text(_sPutLog,1,network.id,16,SQLITE_STATIC); +		sqlite3_bind_text(_sPutLog,2,member.nodeId,10,SQLITE_STATIC); +		sqlite3_bind_int64(_sPutLog,3,(long long)OSUtils::now()); +		sqlite3_bind_int(_sPutLog,4,member.authorized ? 1 : 0); +		if ((clientMajorVersion > 0)||(clientMinorVersion > 0)||(clientRevision > 0)) { +			Utils::snprintf(ver,sizeof(ver),"%u.%u.%u",clientMajorVersion,clientMinorVersion,clientRevision); +			sqlite3_bind_text(_sPutLog,5,ver,-1,SQLITE_STATIC); +		} else sqlite3_bind_null(_sPutLog,5); +		if (fa.length() > 0) +			sqlite3_bind_text(_sPutLog,6,fa.c_str(),-1,SQLITE_STATIC); +		else sqlite3_bind_null(_sPutLog,6); +		sqlite3_step(_sPutLog); +	} +  	// Check member authorization  	if (!member.authorized)  		return NetworkController::NETCONF_QUERY_ACCESS_DENIED; -	// If netconf is unchanged from client reported revision, just tell client they're up to date - -	// Temporarily disabled -- old version didn't do this, and we'll go ahead and -	// test more thoroughly before enabling this optimization. -	//if ((haveRevision > 0)&&(haveRevision == network.revision)) -	//	return NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER; -  	// Create and sign netconf  	netconf.clear(); @@ -555,7 +600,8 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co  				if ((ipNetmaskBits <= 0)||(ipNetmaskBits > 32))  					continue; -				switch((IpAssignmentType)sqlite3_column_int(_sGetIpAssignmentsForNode,0)) { +				const IpAssignmentType ipt = (IpAssignmentType)sqlite3_column_int(_sGetIpAssignmentsForNode,0); +				switch(ipt) {  					case ZT_IP_ASSIGNMENT_TYPE_ADDRESS:  						haveStaticIpAssignment = true;  						break; @@ -566,13 +612,15 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co  						continue;  				} -				// We send both routes and IP assignments -- client knows which is -				// which by whether address ends in all zeroes after netmask. -				char tmp[32]; -				Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)ip[12],(int)ip[13],(int)ip[14],(int)ip[15],ipNetmaskBits); -				if (v4s.length()) -					v4s.push_back(','); -				v4s.append(tmp); +				// 1.0.4 or newer clients support network routes in addition to IPs. +				// Older clients only support IP address / netmask entries. +				if ((clientIs104)||(ipt == ZT_IP_ASSIGNMENT_TYPE_ADDRESS)) { +					char tmp[32]; +					Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d.%d/%d",(int)ip[12],(int)ip[13],(int)ip[14],(int)ip[15],ipNetmaskBits); +					if (v4s.length()) +						v4s.push_back(','); +					v4s.append(tmp); +				}  			}  			if (!haveStaticIpAssignment) { @@ -648,7 +696,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co  		// TODO: IPv6 auto-assign once it's supported in UI  		if (network.isPrivate) { -			CertificateOfMembership com(network.revision,ZT1_CERTIFICATE_OF_MEMBERSHIP_REVISION_MAX_DELTA,nwid,identity.address()); +			CertificateOfMembership com(OSUtils::now(),ZT_NETWORK_AUTOCONF_DELAY + (ZT_NETWORK_AUTOCONF_DELAY / 2),nwid,identity.address());  			if (com.sign(signingId)) // basically can't fail unless our identity is invalid  				netconf[ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP] = com.toString();  			else { @@ -716,6 +764,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(  					char addrs[24];  					Utils::snprintf(addrs,sizeof(addrs),"%.10llx",address); +					int64_t addToNetworkRevision = 0; +  					int64_t memberRowId = 0;  					sqlite3_reset(_sGetMember);  					sqlite3_bind_text(_sGetMember,1,nwids,16,SQLITE_STATIC); @@ -739,6 +789,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(  						sqlite3_reset(_sIncrementMemberRevisionCounter);  						sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC);  						sqlite3_step(_sIncrementMemberRevisionCounter); +						addToNetworkRevision = 1;  					}  					json_value *j = json_parse(body.c_str(),body.length()); @@ -758,6 +809,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(  										sqlite3_reset(_sIncrementMemberRevisionCounter);  										sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC);  										sqlite3_step(_sIncrementMemberRevisionCounter); +										addToNetworkRevision = 1;  									}  								} else if (!strcmp(j->u.object.values[k].name,"activeBridge")) {  									if (j->u.object.values[k].value->type == json_boolean) { @@ -771,6 +823,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(  										sqlite3_reset(_sIncrementMemberRevisionCounter);  										sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC);  										sqlite3_step(_sIncrementMemberRevisionCounter); +										addToNetworkRevision = 1;  									}  								} else if (!strcmp(j->u.object.values[k].name,"ipAssignments")) {  									if (j->u.object.values[k].value->type == json_array) { @@ -814,6 +867,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(  												}  											}  										} +										addToNetworkRevision = 1;  									}  								} @@ -822,6 +876,13 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(  						json_value_free(j);  					} +					if ((addToNetworkRevision > 0)&&(revision > 0)) { +						sqlite3_reset(_sSetNetworkRevision); +						sqlite3_bind_int64(_sSetNetworkRevision,1,revision + addToNetworkRevision); +						sqlite3_bind_text(_sSetNetworkRevision,2,nwids,16,SQLITE_STATIC); +						sqlite3_step(_sSetNetworkRevision); +					} +  					return _doCPGet(path,urlArgs,headers,body,responseBody,responseContentType);  				} // else 404 @@ -1332,58 +1393,33 @@ unsigned int SqliteNetworkController::_doCPGet(  								responseBody.push_back('"');  							} -							responseBody.append("]"); - -							/* It's possible to get the actual netconf dictionary by including these -							 * three URL arguments. The member identity must be the string -							 * serialized identity of this member, and the signing identity must be -							 * the full secret identity of this network controller. The have revision -							 * is optional but would designate the revision our hypothetical client -							 * already has. -							 * -							 * This is primarily for testing and is not used in production. It makes -							 * it easy to test the entire network controller via its JSON API. -							 * -							 * If these arguments are included, three more object fields are returned: -							 * 'netconf', 'netconfResult', and 'netconfResultMessage'. These are all -							 * string fields and contain the actual netconf dictionary, the query -							 * result code, and any verbose message e.g. an error description. */ -							std::map<std::string,std::string>::const_iterator memids(urlArgs.find("memberIdentity")); -							std::map<std::string,std::string>::const_iterator sigids(urlArgs.find("signingIdentity")); -							std::map<std::string,std::string>::const_iterator hrs(urlArgs.find("haveRevision")); -							if ((memids != urlArgs.end())&&(sigids != urlArgs.end())) { -								Dictionary netconf; -								Identity memid,sigid; -								try { -									if (memid.fromString(memids->second)&&sigid.fromString(sigids->second)&&sigid.hasPrivate()) { -										uint64_t hr = 0; -										if (hrs != urlArgs.end()) -											hr = Utils::strToU64(hrs->second.c_str()); -										const char *result = ""; -										switch(this->doNetworkConfigRequest(InetAddress(),sigid,memid,nwid,Dictionary(),hr,netconf)) { -											case NetworkController::NETCONF_QUERY_OK: result = "OK"; break; -											case NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER: result = "OK_BUT_NOT_NEWER"; break; -											case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: result = "OBJECT_NOT_FOUND"; break; -											case NetworkController::NETCONF_QUERY_ACCESS_DENIED: result = "ACCESS_DENIED"; break; -											case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR: result = "INTERNAL_SERVER_ERROR"; break; -											default: result = "(unrecognized result code)"; break; -										} -										responseBody.append(",\n\t\"netconf\": \""); -										responseBody.append(_jsonEscape(netconf.toString().c_str())); -										responseBody.append("\",\n\t\"netconfResult\": \""); -										responseBody.append(result); -										responseBody.append("\",\n\t\"netconfResultMessage\": \""); -										responseBody.append(_jsonEscape(netconf["error"].c_str())); -										responseBody.append("\""); -									} else { -										responseBody.append(",\n\t\"netconf\": \"\",\n\t\"netconfResult\": \"INTERNAL_SERVER_ERROR\",\n\t\"netconfResultMessage\": \"invalid member or signing identity\""); -									} -								} catch ( ... ) { -									responseBody.append(",\n\t\"netconf\": \"\",\n\t\"netconfResult\": \"INTERNAL_SERVER_ERROR\",\n\t\"netconfResultMessage\": \"unexpected exception\""); -								} +							responseBody.append("],\n\t\"recentLog\": ["); + +							sqlite3_reset(_sGetRecentMemberLog); +							sqlite3_bind_text(_sGetRecentMemberLog,1,nwids,16,SQLITE_STATIC); +							sqlite3_bind_text(_sGetRecentMemberLog,2,addrs,10,SQLITE_STATIC); +							bool firstLog = true; +							while (sqlite3_step(_sGetRecentMemberLog) == SQLITE_ROW) { +								responseBody.append(firstLog ? "{" : ",{"); +								firstLog = false; +								responseBody.append("\"ts\":"); +								responseBody.append(reinterpret_cast<const char *>(sqlite3_column_text(_sGetRecentMemberLog,0))); +								responseBody.append((sqlite3_column_int(_sGetRecentMemberLog,1) == 0) ? ",\"authorized\":false,\"version\":" : ",\"authorized\":true,\"version\":"); +								const char *ver = reinterpret_cast<const char *>(sqlite3_column_text(_sGetRecentMemberLog,2)); +								if ((ver)&&(ver[0])) { +									responseBody.push_back('"'); +									responseBody.append(_jsonEscape(ver)); +									responseBody.append("\",\"fromAddr\":"); +								} else responseBody.append("null,\"fromAddr\":"); +								const char *fa = reinterpret_cast<const char *>(sqlite3_column_text(_sGetRecentMemberLog,3)); +								if ((fa)&&(fa[0])) { +									responseBody.push_back('"'); +									responseBody.append(_jsonEscape(fa)); +									responseBody.append("\"}"); +								} else responseBody.append("null}");  							} -							responseBody.append("\n}\n"); +							responseBody.append("]\n}\n");  							responseContentType = "application/json";  							return 200; @@ -1394,8 +1430,11 @@ unsigned int SqliteNetworkController::_doCPGet(  						sqlite3_reset(_sListNetworkMembers);  						sqlite3_bind_text(_sListNetworkMembers,1,nwids,16,SQLITE_STATIC); +						responseBody.append("{"); +						bool firstMember = true;  						while (sqlite3_step(_sListNetworkMembers) == SQLITE_ROW) { -							responseBody.append((responseBody.length() > 0) ? ",\"" : "{\""); +							responseBody.append(firstMember ? "\"" : ",\""); +							firstMember = false;  							responseBody.append((const char *)sqlite3_column_text(_sListNetworkMembers,0));  							responseBody.append("\":");  							responseBody.append((const char *)sqlite3_column_text(_sListNetworkMembers,1)); diff --git a/controller/SqliteNetworkController.hpp b/controller/SqliteNetworkController.hpp index 8b39f7d9..adfe0991 100644 --- a/controller/SqliteNetworkController.hpp +++ b/controller/SqliteNetworkController.hpp @@ -97,6 +97,9 @@ private:  	std::string _dbPath;  	std::string _instanceId; + +	std::map< std::pair<Address,uint64_t>,uint64_t > _lastRequestTime; +  	sqlite3 *_db;  	sqlite3_stmt *_sGetNetworkById; @@ -141,6 +144,9 @@ private:  	sqlite3_stmt *_sIncrementMemberRevisionCounter;  	sqlite3_stmt *_sGetConfig;  	sqlite3_stmt *_sSetConfig; +	sqlite3_stmt *_sPutLog; +	sqlite3_stmt *_sGetMemberLog; +	sqlite3_stmt *_sGetRecentMemberLog;  	Mutex _lock;  }; diff --git a/controller/schema.sql b/controller/schema.sql index e85785b7..398d63ac 100644 --- a/controller/schema.sql +++ b/controller/schema.sql @@ -65,6 +65,18 @@ CREATE TABLE Member (  CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);  CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision); +CREATE TABLE Log ( +  networkId char(16) NOT NULL, +  nodeId char(10) NOT NULL, +  ts integer NOT NULL, +  authorized integer NOT NULL, +  version varchar(16), +  fromAddr varchar(64) +); + +CREATE INDEX Log_networkId_nodeId ON Log(networkId, nodeId); +CREATE INDEX Log_ts ON Log(ts); +  CREATE TABLE Relay (    networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,    address char(10) NOT NULL, diff --git a/controller/schema.sql.c b/controller/schema.sql.c index efeb280c..fa83f880 100644 --- a/controller/schema.sql.c +++ b/controller/schema.sql.c @@ -66,6 +66,18 @@  "CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\  "CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision);\n"\  "\n"\ +"CREATE TABLE Log (\n"\ +"  networkId char(16) NOT NULL,\n"\ +"  nodeId char(10) NOT NULL,\n"\ +"  ts integer NOT NULL,\n"\ +"  authorized integer NOT NULL,\n"\ +"  version varchar(16),\n"\ +"  fromAddr varchar(64)\n"\ +");\n"\ +"\n"\ +"CREATE INDEX Log_networkId_nodeId ON Log(networkId, nodeId);\n"\ +"CREATE INDEX Log_ts ON Log(ts);\n"\ +"\n"\  "CREATE TABLE Relay (\n"\  "  networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\  "  address char(10) NOT NULL,\n"\ diff --git a/ext/bin/miniupnpc/Changelog.txt b/ext/bin/miniupnpc/Changelog.txt new file mode 100644 index 00000000..bb2abb7e --- /dev/null +++ b/ext/bin/miniupnpc/Changelog.txt @@ -0,0 +1,633 @@ +$Id: Changelog.txt,v 1.208 2015/07/15 12:18:59 nanard Exp $ +miniUPnP client Changelog. + +2015/07/15: +  Check malloc/calloc + +2015/06/16: +  update getDevicesFromMiniSSDPD() to process longer minissdpd +    responses + +2015/05/22: +  add searchalltypes param to upnpDiscoverDevices() +  increments API_VERSION to 13 + +2015/04/30: +  upnpc: output version on the terminal + +2015/04/27: +  _BSD_SOURCE is deprecated in favor of _DEFAULT_SOURCE +  fix CMakeLists.txt COMPILE_DEFINITIONS +  fix getDevicesFromMiniSSDPD() not setting scope_id +  improve -r command of upnpc command line tool + +2014/11/17: +  search all : +    upnpDiscoverDevices() / upnpDiscoverAll() functions +    listdevices executable +  increment API_VERSION to 12 +  validate igd_desc_parse + +2014/11/13: +  increment API_VERSION to 11 + +2014/11/05: +  simplified function GetUPNPUrls() + +2014/09/11: +  use remoteHost arg of DeletePortMapping + +2014/09/06: +  Fix python3 build + +2014/07/01: +  Fix parsing of IGD2 root descriptions + +2014/06/10: +  rename LIBSPEC to MINIUPNP_LIBSPEC + +2014/05/15: +  Add support for IGD2 AddAnyPortMapping and DeletePortMappingRange + +2014/02/05: +  handle EINPROGRESS after connect() + +2014/02/03: +  minixml now handle XML comments + +VERSION 1.9 : released 2014/01/31 + +2014/01/31: +  added argument remoteHost to UPNP_GetSpecificPortMappingEntry() +  increment API_VERSION to 10 + +2013/12/09: +  --help and -h arguments in upnpc.c + +2013/10/07: +  fixed potential buffer overrun in miniwget.c +  Modified UPNP_GetValidIGD() to check for ExternalIpAddress + +2013/08/01: +  define MAXHOSTNAMELEN if not already done + +2013/06/06: +  update upnpreplyparse to allow larger values (128 chars instead of 64) + +2013/05/14: +  Update upnpreplyparse to take into account "empty" elements +  validate upnpreplyparse.c code with "make check" + +2013/05/03: +  Fix Solaris build thanks to Maciej Małecki + +2013/04/27: +  Fix testminiwget.sh for BSD + +2013/03/23: +  Fixed Makefile for *BSD + +2013/03/11: +  Update Makefile to use JNAerator version 0.11 + +2013/02/11: +  Fix testminiwget.sh for use with dash +  Use $(DESTDIR) in Makefile + +VERSION 1.8 : released 2013/02/06 + +2012/10/16: +  fix testminiwget with no IPv6 support + +2012/09/27: +  Rename all include guards to not clash with C99 +  (7.1.3 Reserved identifiers). + +2012/08/30: +  Added -e option to upnpc program (set description for port mappings) + +2012/08/29: +  Python 3 support (thanks to Christopher Foo) + +2012/08/11: +  Fix a memory link in UPNP_GetValidIGD() +  Try to handle scope id in link local IPv6 URL under MS Windows + +2012/07/20: +  Disable HAS_IP_MREQN on DragonFly BSD + +2012/06/28: +  GetUPNPUrls() now inserts scope into link-local IPv6 addresses + +2012/06/23: +  More error return checks in upnpc.c +  #define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id +  parseURL() now parses IPv6 addresses scope +  new parameter for miniwget() : IPv6 address scope +  increment API_VERSION to 9 + +2012/06/20: +  fixed CMakeLists.txt + +2012/05/29 +  Improvements in testminiwget.sh + +VERSION 1.7 : released 2012/05/24 + +2012/05/01: +  Cleanup settings of CFLAGS in Makefile +  Fix signed/unsigned integer comparaisons + +2012/04/20: +  Allow to specify protocol with TCP or UDP for -A option + +2012/04/09: +  Only try to fetch XML description once in UPNP_GetValidIGD() +  Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments. + +2012/04/05: +  minor improvements to minihttptestserver.c + +2012/03/15: +  upnperrors.c returns valid error string for unrecognized error codes + +2012/03/08: +  make minihttptestserver listen on loopback interface instead of 0.0.0.0 + +2012/01/25: +  Maven installation thanks to Alexey Kuznetsov + +2012/01/21: +  Replace WIN32 macro by _WIN32 + +2012/01/19: +  Fixes in java wrappers thanks to Alexey Kuznetsov : +    https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc +  Make and install .deb packages (python) thanks to Alexey Kuznetsov : +    https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc + +2012/01/07: +  The multicast interface can now be specified by name with IPv4. + +2012/01/02: +  Install man page + +2011/11/25: +  added header to Port Mappings list in upnpc.c + +2011/10/09: +  Makefile : make clean now removes jnaerator generated files. +  MINIUPNPC_VERSION in miniupnpc.h (updated by make) + +2011/09/12: +  added rootdescURL to UPNPUrls structure. + +VERSION 1.6 : released 2011/07/25 + +2011/07/25: +  Update doc for version 1.6 release + +2011/06/18: +  Fix for windows in miniwget.c + +2011/06/04: +  display remote host in port mapping listing + +2011/06/03: +  Fix in make install : there were missing headers + +2011/05/26: +  Fix the socket leak in miniwget thanks to Richard Marsh. +  Permit to add leaseduration in -a command. Display lease duration. + +2011/05/15: +  Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6 + +2011/05/09: +  add a test in testminiwget.sh. +  more error checking in miniwget.c + +2011/05/06: +  Adding some tool to test and validate miniwget.c +  simplified and debugged miniwget.c + +2011/04/11: +  moving ReceiveData() to a receivedata.c file. +  parsing presentation url +  adding IGD v2 WANIPv6FirewallControl commands + +2011/04/10: +  update of miniupnpcmodule.c +  comments in miniwget.c, update in testminiwget +  Adding errors codes from IGD v2 +  new functions in upnpc.c for IGD v2 + +2011/04/09: +  Support for litteral ip v6 address in miniwget + +2011/04/08: +  Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 +  Updating APIVERSION +  Supporting IPV6 in upnpDiscover() +  Adding a -6 option to upnpc command line tool + +2011/03/18: +  miniwget/parseURL() : return an error when url param is null. +  fixing GetListOfPortMappings() + +2011/03/14: +  upnpDiscover() now reporting an error code. +  improvements in comments. + +2011/03/11: +  adding miniupnpcstrings.h.cmake and CMakeLists.txt files. + +2011/02/15: +  Implementation of GetListOfPortMappings() + +2011/02/07: +  updates to minixml to support character data starting with spaces +  minixml now support CDATA +  upnpreplyparse treats <NewPortListing> specificaly +  change in simpleUPnPcommand to return the buffer (simplification) + +2011/02/06: +  Added leaseDuration argument to AddPortMapping() +  Starting to implement GetListOfPortMappings() + +2011/01/11: +  updating wingenminiupnpcstrings.c + +2011/01/04: +  improving updateminiupnpcstrings.sh + +VERSION 1.5 : released 2011/01/01 + +2010/12/21: +  use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo + +2010/12/11: +  Improvements on getHTTPResponse() code. + +2010/12/09: +  new code for miniwget that handle Chunked transfer encoding +  using getHTTPResponse() in SOAP call code +  Adding MANIFEST.in for 'python setup.py bdist_rpm' + +2010/11/25: +  changes to minissdpc.c to compile under Win32. +  see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729 + +2010/09/17: +  Various improvement to Makefile from Michał Górny + +2010/08/05: +  Adding the script "external-ip.sh" from Reuben Hawkins + +2010/06/09: +  update to python module to match modification made on 2010/04/05 +  update to Java test code to match modification made on 2010/04/05 +  all UPNP_* function now return an error if the SOAP request failed +  at HTTP level. + +2010/04/17: +  Using GetBestRoute() under win32 in order to find the +  right interface to use. + +2010/04/12: +  Retrying with HTTP/1.1 if HTTP/1.0 failed. see +  http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703 + +2010/04/07: +  avoid returning duplicates in upnpDiscover() + +2010/04/05: +  Create a connecthostport.h/.c with connecthostport() function +  and use it in miniwget and miniupnpc. +  Use getnameinfo() instead of inet_ntop or inet_ntoa +  Work to make miniupnpc IPV6 compatible... +  Add java test code. +  Big changes in order to support device having both WANIPConnection +  and WANPPPConnection. + +2010/04/04: +  Use getaddrinfo() instead of gethostbyname() in miniwget. + +2010/01/06: +  #define _DARWIN_C_SOURCE for Mac OS X + +2009/12/19: +  Improve MinGW32 build + +2009/12/11: +  adding a MSVC9 project to build the static library and executable + +2009/12/10: +  Fixing some compilation stuff for Windows/MinGW + +2009/12/07: +  adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS +  some fixes for Windows when using virtual ethernet adapters (it is the +  case with VMWare installed). + +2009/12/04: +  some fixes for AmigaOS compilation +  Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked +  transfer encoding) + +2009/12/03: +  updating printIDG and testigddescparse.c for debug. +  modifications to compile under AmigaOS +  adding a testminiwget program +  Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked +  transfer encoding + +2009/11/26: +  fixing updateminiupnpcstrings.sh to take into account +  which command that does not return an error code. + +VERSION 1.4 : released 2009/10/30 + +2009/10/16: +  using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module. + +2009/10/10: +  Some fixes for compilation under Solaris +  compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464 + +2009/09/21: +  fixing the code to ignore EINTR during connect() calls. + +2009/08/07: +  Set socket timeout for connect() +  Some cleanup in miniwget.c + +2009/08/04: +  remove multiple redirections with -d in upnpc.c +  Print textual error code in upnpc.c +  Ignore EINTR during the connect() and poll() calls. + +2009/07/29: +  fix in updateminiupnpcstrings.sh if OS name contains "/" +  Sending a correct value for MX: field in SSDP request + +2009/07/20: +  Change the Makefile to compile under Mac OS X +  Fixed a stackoverflow in getDevicesFromMiniSSDPD() + +2009/07/09: +  Compile under Haiku +  generate miniupnpcstrings.h.in from miniupnpcstrings.h + +2009/06/04: +  patching to compile under CygWin and cross compile for minGW + +VERSION 1.3 : + +2009/04/17: +  updating python module +  Use strtoull() when using C99 + +2009/02/28: +  Fixed miniwget.c for compiling under sun + +2008/12/18: +  cleanup in Makefile (thanks to Paul de Weerd) +  minissdpc.c : win32 compatibility +  miniupnpc.c : changed xmlns prefix from 'm' to 'u' +  Removed NDEBUG (using DEBUG) + +2008/10/14: +  Added the ExternalHost argument to DeletePortMapping() + +2008/10/11: +  Added the ExternalHost argument to AddPortMapping() +  Put a correct User-Agent: header in HTTP requests. + +VERSION 1.2 : + +2008/10/07: +  Update docs + +2008/09/25: +  Integrated sameport patch from Dario Meloni : Added a "sameport" +  argument to upnpDiscover(). + +2008/07/18: +  small modif to make Clang happy :) + +2008/07/17: +  #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV... + +2008/07/14: +  include declspec.h in installation (to /usr/include/miniupnpc) + +VERSION 1.1 : + +2008/07/04: +  standard options for install/ln instead of gnu-specific stuff. + +2008/07/03: +  now builds a .dll and .lib with win32. (mingw32) + +2008/04/28: +  make install now install the binary of the upnpc tool + +2008/04/27: +  added testupnpigd.py +  added error strings for miniupnpc "internal" errors +  improved python module error/exception reporting. + +2008/04/23: +  Completely rewrite igd_desc_parse.c in order to be compatible with +  Linksys WAG200G +  Added testigddescparse +  updated python module + +VERSION 1.0 : + +2008/02/21: +  put some #ifdef DEBUG around DisplayNameValueList() + +2008/02/18: +  Improved error reporting in upnpcommands.c +  UPNP_GetStatusInfo() returns LastConnectionError + +2008/02/16: +  better error handling in minisoap.c +  improving display of "valid IGD found" in upnpc.c + +2008/02/03: +  Fixing UPNP_GetValidIGD() +  improved make install :) + +2007/12/22: +  Adding upnperrors.c/h to provide a strupnperror() function +  used to translate UPnP error codes to string. + +2007/12/19: +  Fixing getDevicesFromMiniSSDPD() +  improved error reporting of UPnP functions + +2007/12/18: +  It is now possible to specify a different location for MiniSSDPd socket. +  working with MiniSSDPd is now more efficient. +  python module improved. + +2007/12/16: +  improving error reporting + +2007/12/13: +  Try to improve compatibility by using HTTP/1.0 instead of 1.1 and +  XML a bit different for SOAP. + +2007/11/25: +  fixed select() call for linux + +2007/11/15: +  Added -fPIC to CFLAG for better shared library code. + +2007/11/02: +  Fixed a potential socket leak in miniwget2() + +2007/10/16: +  added a parameter to upnpDiscover() in order to allow the use of another +  interface than the default multicast interface. + +2007/10/12: +  Fixed the creation of symbolic link in Makefile + +2007/10/08: +  Added man page + +2007/10/02: +  fixed memory bug in GetUPNPUrls() + +2007/10/01: +  fixes in the Makefile +  Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly. +  Added SONAME in the shared library to please debian :) +  fixed MS Windows compilation (minissdpd is not available under MS Windows). + +2007/09/25: +  small change to Makefile to be able to install in a different location +  (default is /usr) + +2007/09/24: +  now compiling both shared and static library + +2007/09/19: +  Cosmetic changes on upnpc.c + +2007/09/02: +  adapting to new miniSSDPd (release version ?) + +2007/08/31: +  Usage of miniSSDPd to skip discovery process. + +2007/08/27: +  fixed python module to allow compilation with Python older than Python 2.4 + +2007/06/12: +  Added a python module. + +2007/05/19: +  Fixed compilation under MinGW + +2007/05/15: +  fixed a memory leak in AddPortMapping() +  Added testupnpreplyparse executable to check the parsing of +  upnp soap messages +  minixml now ignore namespace prefixes. + +2007/04/26: +  upnpc now displays external ip address with -s or -l + +2007/04/11: +  changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210" + +2007/03/19: +  cleanup in miniwget.c + +2007/03/01: +  Small typo fix... + +2007/01/30: +  Now parsing the HTTP header from SOAP responses in order to +  get content-length value. + +2007/01/29: +  Fixed the Soap Query to speedup the HTTP request. +  added some Win32 DLL stuff... + +2007/01/27: +  Fixed some WIN32 compatibility issues + +2006/12/14: +  Added UPNPIGD_IsConnected() function in miniupnp.c/.h +  Added UPNP_GetValidIGD() in miniupnp.c/.h +  cleaned upnpc.c main(). now using UPNP_GetValidIGD() + +2006/12/07: +  Version 1.0-RC1 released + +2006/12/03: +  Minor changes to compile under SunOS/Solaris + +2006/11/30: +  made a minixml parser validator program +  updated minixml to handle attributes correctly + +2006/11/22: +  Added a -r option to the upnpc sample thanks to Alexander Hubmann. + +2006/11/19: +  Cleanup code to make it more ANSI C compliant + +2006/11/10: +  detect and display local lan address. + +2006/11/04: +  Packets and Bytes Sent/Received are now unsigned int. + +2006/11/01: +  Bug fix thanks to Giuseppe D'Angelo + +2006/10/31: +  C++ compatibility for .h files. +  Added a way to get ip Address on the LAN used to reach the IGD. + +2006/10/25: +  Added M-SEARCH to the services in the discovery process. + +2006/10/22: +  updated the Makefile to use makedepend, added a "make install" +  update Makefile + +2006/10/20: +  fixing the description url parsing thanks to patch sent by +  Wayne Dawe. +  Fixed/translated some comments. +  Implemented a better discover process, first looking +  for IGD then for root devices (as some devices only reply to +  M-SEARCH for root devices). + +2006/09/02: +  added freeUPNPDevlist() function. + +2006/08/04: +  More command line arguments checking + +2006/08/01: +  Added the .bat file to compile under Win32 with minGW32 + +2006/07/31: +  Fixed the rootdesc parser (igd_desc_parse.c) + +2006/07/20: +  parseMSEARCHReply() is now returning the ST: line as well +  starting changes to detect several UPnP devices on the network + +2006/07/19: +  using GetCommonLinkProperties to get down/upload bitrate + diff --git a/ext/bin/miniupnpc/LICENSE b/ext/bin/miniupnpc/LICENSE new file mode 100644 index 00000000..cb5a0604 --- /dev/null +++ b/ext/bin/miniupnpc/LICENSE @@ -0,0 +1,27 @@ +MiniUPnPc +Copyright (c) 2005-2015, Thomas BERNARD +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +    * Redistributions of source code must retain the above copyright notice, +      this list of conditions and the following disclaimer. +    * Redistributions in binary form must reproduce the above copyright notice, +      this list of conditions and the following disclaimer in the documentation +      and/or other materials provided with the distribution. +    * The name of the author may not be used to endorse or promote products +	  derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/ext/bin/miniupnpc/README.md b/ext/bin/miniupnpc/README.md new file mode 100644 index 00000000..c3d538ba --- /dev/null +++ b/ext/bin/miniupnpc/README.md @@ -0,0 +1,4 @@ +libminiupnpc binaries +====== + +This is a binary build of [libminiupnpc](http://miniupnp.free.fr) for certain architectures to faciliate easy building. Where possible the build flags were set for improved security by enabling options like stack protector (a.k.a. stack canary), ASLR support, etc. diff --git a/ext/bin/miniupnpc/VERSION b/ext/bin/miniupnpc/VERSION new file mode 100644 index 00000000..2e0e38c6 --- /dev/null +++ b/ext/bin/miniupnpc/VERSION @@ -0,0 +1 @@ +1.9 diff --git a/ext/bin/miniupnpc/include/miniupnpc/codelength.h b/ext/bin/miniupnpc/include/miniupnpc/codelength.h new file mode 100644 index 00000000..f5f8e30f --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/codelength.h @@ -0,0 +1,54 @@ +/* $Id: codelength.h,v 1.5 2015/07/09 12:40:18 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas BERNARD + * copyright (c) 2005-2015 Thomas Bernard + * This software is subjet to the conditions detailed in the + * provided LICENCE file. */ +#ifndef CODELENGTH_H_INCLUDED +#define CODELENGTH_H_INCLUDED + +/* Encode length by using 7bit per Byte : + * Most significant bit of each byte specifies that the + * following byte is part of the code */ + +/* n : unsigned + * p : unsigned char * + */ +#define DECODELENGTH(n, p) n = 0; \ +                           do { n = (n << 7) | (*p & 0x7f); } \ +                           while((*(p++)&0x80) && (n<(1<<25))); + +/* n :    unsigned + * READ : function/macro to read one byte (unsigned char) + */ +#define DECODELENGTH_READ(n, READ) \ +	n = 0; \ +	do { \ +		unsigned char c; \ +		READ(c); \ +		n = (n << 7) | (c & 0x07f); \ +		if(!(c&0x80)) break; \ +	} while(n<(1<<25)); + +/* n :       unsigned + * p :       unsigned char * + * p_limit : unsigned char * + */ +#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \ +	n = 0; \ +	do { \ +		if((p) >= (p_limit)) break; \ +		n = (n << 7) | (*(p) & 0x7f); \ +	} while((*((p)++)&0x80) && (n<(1<<25))); + + +/* n : unsigned + * p : unsigned char * + */ +#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \ +                         if(n>=2097152) *(p++) = (n >> 21) | 0x80; \ +                         if(n>=16384) *(p++) = (n >> 14) | 0x80; \ +                         if(n>=128) *(p++) = (n >> 7) | 0x80; \ +                         *(p++) = n & 0x7f; + +#endif /* CODELENGTH_H_INCLUDED */ diff --git a/ext/bin/miniupnpc/include/miniupnpc/connecthostport.h b/ext/bin/miniupnpc/include/miniupnpc/connecthostport.h new file mode 100644 index 00000000..56941d6f --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/connecthostport.h @@ -0,0 +1,18 @@ +/* $Id: connecthostport.h,v 1.3 2012/09/27 15:42:10 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ + * Author: Thomas Bernard + * Copyright (c) 2010-2012 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef CONNECTHOSTPORT_H_INCLUDED +#define CONNECTHOSTPORT_H_INCLUDED + +/* connecthostport() + * return a socket connected (TCP) to the host and port + * or -1 in case of error */ +int connecthostport(const char * host, unsigned short port, +                    unsigned int scope_id); + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/igd_desc_parse.h b/ext/bin/miniupnpc/include/miniupnpc/igd_desc_parse.h new file mode 100644 index 00000000..0de546b6 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/igd_desc_parse.h @@ -0,0 +1,49 @@ +/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */ +/* Project : miniupnp + * http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2005-2014 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#ifndef IGD_DESC_PARSE_H_INCLUDED +#define IGD_DESC_PARSE_H_INCLUDED + +/* Structure to store the result of the parsing of UPnP + * descriptions of Internet Gateway Devices */ +#define MINIUPNPC_URL_MAXSIZE (128) +struct IGDdatas_service { +	char controlurl[MINIUPNPC_URL_MAXSIZE]; +	char eventsuburl[MINIUPNPC_URL_MAXSIZE]; +	char scpdurl[MINIUPNPC_URL_MAXSIZE]; +	char servicetype[MINIUPNPC_URL_MAXSIZE]; +	/*char devicetype[MINIUPNPC_URL_MAXSIZE];*/ +}; + +struct IGDdatas { +	char cureltname[MINIUPNPC_URL_MAXSIZE]; +	char urlbase[MINIUPNPC_URL_MAXSIZE]; +	char presentationurl[MINIUPNPC_URL_MAXSIZE]; +	int level; +	/*int state;*/ +	/* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */ +	struct IGDdatas_service CIF; +	/* "urn:schemas-upnp-org:service:WANIPConnection:1" +	 * "urn:schemas-upnp-org:service:WANPPPConnection:1" */ +	struct IGDdatas_service first; +	/* if both WANIPConnection and WANPPPConnection are present */ +	struct IGDdatas_service second; +	/* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */ +	struct IGDdatas_service IPv6FC; +	/* tmp */ +	struct IGDdatas_service tmp; +}; + +void IGDstartelt(void *, const char *, int); +void IGDendelt(void *, const char *, int); +void IGDdata(void *, const char *, int); +#ifdef DEBUG +void printIGD(struct IGDdatas *); +#endif /* DEBUG */ + +#endif /* IGD_DESC_PARSE_H_INCLUDED */ diff --git a/ext/bin/miniupnpc/include/miniupnpc/minisoap.h b/ext/bin/miniupnpc/include/miniupnpc/minisoap.h new file mode 100644 index 00000000..14c859d1 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/minisoap.h @@ -0,0 +1,15 @@ +/* $Id: minisoap.h,v 1.5 2012/09/27 15:42:10 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. */ +#ifndef MINISOAP_H_INCLUDED +#define MINISOAP_H_INCLUDED + +/*int httpWrite(int, const char *, int, const char *);*/ +int soapPostSubmit(int, const char *, const char *, unsigned short, +		   const char *, const char *, const char *); + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/minissdpc.h b/ext/bin/miniupnpc/include/miniupnpc/minissdpc.h new file mode 100644 index 00000000..915b0026 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/minissdpc.h @@ -0,0 +1,15 @@ +/* $Id: minissdpc.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2005-2007 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef MINISSDPC_H_INCLUDED +#define MINISSDPC_H_INCLUDED + +struct UPNPDev * +getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath); + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h b/ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h new file mode 100644 index 00000000..0eeabc23 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h @@ -0,0 +1,154 @@ +/* $Id: miniupnpc.h,v 1.42 2015/07/21 13:16:55 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ + * Author: Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef MINIUPNPC_H_INCLUDED +#define MINIUPNPC_H_INCLUDED + +#include "miniupnpc_declspec.h" +#include "igd_desc_parse.h" + +/* error codes : */ +#define UPNPDISCOVER_SUCCESS (0) +#define UPNPDISCOVER_UNKNOWN_ERROR (-1) +#define UPNPDISCOVER_SOCKET_ERROR (-101) +#define UPNPDISCOVER_MEMORY_ERROR (-102) + +/* versions : */ +#define MINIUPNPC_VERSION	"1.9.20150721" +#define MINIUPNPC_API_VERSION	13 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structures definitions : */ +struct UPNParg { const char * elt; const char * val; }; + +char * +simpleUPnPcommand(int, const char *, const char *, +                  const char *, struct UPNParg *, +                  int *); + +struct UPNPDev { +	struct UPNPDev * pNext; +	char * descURL; +	char * st; +	unsigned int scope_id; +	char buffer[2]; +}; + +/* upnpDiscover() + * discover UPnP devices on the network. + * The discovered devices are returned as a chained list. + * It is up to the caller to free the list with freeUPNPDevlist(). + * delay (in millisecond) is the maximum time for waiting any device + * response. + * If available, device list will be obtained from MiniSSDPd. + * Default path for minissdpd socket will be used if minissdpdsock argument + * is NULL. + * If multicastif is not NULL, it will be used instead of the default + * multicast interface for sending SSDP discover packets. + * If sameport is not null, SSDP packets will be sent from the source port + * 1900 (same as destination port) otherwise system assign a source port. + * "searchalltypes" parameter is useful when searching several types, + * if 0, the discovery will stop with the first type returning results. */ +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscover(int delay, const char * multicastif, +             const char * minissdpdsock, int sameport, +             int ipv6, +             int * error); + +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscoverAll(int delay, const char * multicastif, +                const char * minissdpdsock, int sameport, +                int ipv6, +                int * error); + +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscoverDevice(const char * device, int delay, const char * multicastif, +                const char * minissdpdsock, int sameport, +                int ipv6, +                int * error); + +MINIUPNP_LIBSPEC struct UPNPDev * +upnpDiscoverDevices(const char * const deviceTypes[], +                    int delay, const char * multicastif, +                    const char * minissdpdsock, int sameport, +                    int ipv6, +                    int * error, +                    int searchalltypes); + +/* freeUPNPDevlist() + * free list returned by upnpDiscover() */ +MINIUPNP_LIBSPEC void freeUPNPDevlist(struct UPNPDev * devlist); + +/* parserootdesc() : + * parse root XML description of a UPnP device and fill the IGDdatas + * structure. */ +MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *); + +/* structure used to get fast access to urls + * controlURL: controlURL of the WANIPConnection + * ipcondescURL: url of the description of the WANIPConnection + * controlURL_CIF: controlURL of the WANCommonInterfaceConfig + * controlURL_6FC: controlURL of the WANIPv6FirewallControl + */ +struct UPNPUrls { +	char * controlURL; +	char * ipcondescURL; +	char * controlURL_CIF; +	char * controlURL_6FC; +	char * rootdescURL; +}; + +/* UPNP_GetValidIGD() : + * return values : + *     0 = NO IGD found + *     1 = A valid connected IGD has been found + *     2 = A valid IGD has been found but it reported as + *         not connected + *     3 = an UPnP device has been found but was not recognized as an IGD + * + * In any non zero return case, the urls and data structures + * passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to + * free allocated memory. + */ +MINIUPNP_LIBSPEC int +UPNP_GetValidIGD(struct UPNPDev * devlist, +                 struct UPNPUrls * urls, +				 struct IGDdatas * data, +				 char * lanaddr, int lanaddrlen); + +/* UPNP_GetIGDFromUrl() + * Used when skipping the discovery process. + * When succeding, urls, data, and lanaddr arguments are set. + * return value : + *   0 - Not ok + *   1 - OK */ +MINIUPNP_LIBSPEC int +UPNP_GetIGDFromUrl(const char * rootdescurl, +                   struct UPNPUrls * urls, +                   struct IGDdatas * data, +                   char * lanaddr, int lanaddrlen); + +MINIUPNP_LIBSPEC void +GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *, +            const char *, unsigned int); + +MINIUPNP_LIBSPEC void +FreeUPNPUrls(struct UPNPUrls *); + +/* return 0 or 1 */ +MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniupnpc_declspec.h b/ext/bin/miniupnpc/include/miniupnpc/miniupnpc_declspec.h new file mode 100644 index 00000000..40adb922 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/miniupnpc_declspec.h @@ -0,0 +1,21 @@ +#ifndef MINIUPNPC_DECLSPEC_H_INCLUDED +#define MINIUPNPC_DECLSPEC_H_INCLUDED + +#if defined(_WIN32) && !defined(MINIUPNP_STATICLIB) +	/* for windows dll */ +	#ifdef MINIUPNP_EXPORTS +		#define MINIUPNP_LIBSPEC __declspec(dllexport) +	#else +		#define MINIUPNP_LIBSPEC __declspec(dllimport) +	#endif +#else +	#if defined(__GNUC__) && __GNUC__ >= 4 +		/* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */ +		#define MINIUPNP_LIBSPEC __attribute__ ((visibility ("default"))) +	#else +		#define MINIUPNP_LIBSPEC +	#endif +#endif + +#endif /* MINIUPNPC_DECLSPEC_H_INCLUDED */ + diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniupnpcstrings.h b/ext/bin/miniupnpc/include/miniupnpc/miniupnpcstrings.h new file mode 100644 index 00000000..80a1d757 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/miniupnpcstrings.h @@ -0,0 +1,23 @@ +/* $Id: miniupnpcstrings.h.in,v 1.6 2014/11/04 22:31:55 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2005-2014 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef MINIUPNPCSTRINGS_H_INCLUDED +#define MINIUPNPCSTRINGS_H_INCLUDED + +#define OS_STRING "Darwin/14.4.0" +#define MINIUPNPC_VERSION_STRING "1.9" + +#if 0 +/* according to "UPnP Device Architecture 1.0" */ +#define UPNP_VERSION_STRING "UPnP/1.0" +#else +/* according to "UPnP Device Architecture 1.1" */ +#define UPNP_VERSION_STRING "UPnP/1.1" +#endif + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniupnpctypes.h b/ext/bin/miniupnpc/include/miniupnpc/miniupnpctypes.h new file mode 100644 index 00000000..591c32fb --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/miniupnpctypes.h @@ -0,0 +1,19 @@ +/* $Id: miniupnpctypes.h,v 1.2 2012/09/27 15:42:10 nanard Exp $ */ +/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org + * Author : Thomas Bernard + * Copyright (c) 2011 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided within this distribution */ +#ifndef MINIUPNPCTYPES_H_INCLUDED +#define MINIUPNPCTYPES_H_INCLUDED + +#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) +#define UNSIGNED_INTEGER unsigned long long +#define STRTOUI	strtoull +#else +#define UNSIGNED_INTEGER unsigned int +#define STRTOUI	strtoul +#endif + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/miniwget.h b/ext/bin/miniupnpc/include/miniupnpc/miniwget.h new file mode 100644 index 00000000..d6db71a8 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/miniwget.h @@ -0,0 +1,30 @@ +/* $Id: miniwget.h,v 1.10 2015/07/21 13:16:55 nanard Exp $ */ +/* Project : miniupnp + * Author : Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#ifndef MINIWGET_H_INCLUDED +#define MINIWGET_H_INCLUDED + +#include "miniupnpc_declspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MINIUPNP_LIBSPEC void * getHTTPResponse(int s, int * size); + +MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int); + +MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int); + +int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/minixml.h b/ext/bin/miniupnpc/include/miniupnpc/minixml.h new file mode 100644 index 00000000..9f43aa48 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/minixml.h @@ -0,0 +1,37 @@ +/* $Id: minixml.h,v 1.7 2012/09/27 15:42:10 nanard Exp $ */ +/* minimal xml parser + * + * Project : miniupnp + * Website : http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2005 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided in this distribution. + * */ +#ifndef MINIXML_H_INCLUDED +#define MINIXML_H_INCLUDED +#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n')) + +/* if a callback function pointer is set to NULL, + * the function is not called */ +struct xmlparser { +	const char *xmlstart; +	const char *xmlend; +	const char *xml;	/* pointer to current character */ +	int xmlsize; +	void * data; +	void (*starteltfunc) (void *, const char *, int); +	void (*endeltfunc) (void *, const char *, int); +	void (*datafunc) (void *, const char *, int); +	void (*attfunc) (void *, const char *, int, const char *, int); +}; + +/* parsexml() + * the xmlparser structure must be initialized before the call + * the following structure members have to be initialized : + * xmlstart, xmlsize, data, *func + * xml is for internal usage, xmlend is computed automatically */ +void parsexml(struct xmlparser *); + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/portlistingparse.h b/ext/bin/miniupnpc/include/miniupnpc/portlistingparse.h new file mode 100644 index 00000000..661ad1fa --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/portlistingparse.h @@ -0,0 +1,65 @@ +/* $Id: portlistingparse.h,v 1.11 2015/07/21 13:16:55 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2011-2015 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ +#ifndef PORTLISTINGPARSE_H_INCLUDED +#define PORTLISTINGPARSE_H_INCLUDED + +#include "miniupnpc_declspec.h" +/* for the definition of UNSIGNED_INTEGER */ +#include "miniupnpctypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* sample of PortMappingEntry : +  <p:PortMappingEntry> +    <p:NewRemoteHost>202.233.2.1</p:NewRemoteHost> +    <p:NewExternalPort>2345</p:NewExternalPort> +    <p:NewProtocol>TCP</p:NewProtocol> +    <p:NewInternalPort>2345</p:NewInternalPort> +    <p:NewInternalClient>192.168.1.137</p:NewInternalClient> +    <p:NewEnabled>1</p:NewEnabled> +    <p:NewDescription>dooom</p:NewDescription> +    <p:NewLeaseTime>345</p:NewLeaseTime> +  </p:PortMappingEntry> + */ +typedef enum { PortMappingEltNone, +       PortMappingEntry, NewRemoteHost, +       NewExternalPort, NewProtocol, +       NewInternalPort, NewInternalClient, +       NewEnabled, NewDescription, +       NewLeaseTime } portMappingElt; + +struct PortMapping { +	struct PortMapping * l_next;	/* list next element */ +	UNSIGNED_INTEGER leaseTime; +	unsigned short externalPort; +	unsigned short internalPort; +	char remoteHost[64]; +	char internalClient[64]; +	char description[64]; +	char protocol[4]; +	unsigned char enabled; +}; + +struct PortMappingParserData { +	struct PortMapping * l_head;	/* list head */ +	portMappingElt curelt; +}; + +MINIUPNP_LIBSPEC void +ParsePortListing(const char * buffer, int bufsize, +                 struct PortMappingParserData * pdata); + +MINIUPNP_LIBSPEC void +FreePortListing(struct PortMappingParserData * pdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/bin/miniupnpc/include/miniupnpc/receivedata.h b/ext/bin/miniupnpc/include/miniupnpc/receivedata.h new file mode 100644 index 00000000..0520a11d --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/receivedata.h @@ -0,0 +1,19 @@ +/* $Id: receivedata.h,v 1.4 2012/09/27 15:42:10 nanard Exp $ */ +/* Project: miniupnp + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2011-2012 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef RECEIVEDATA_H_INCLUDED +#define RECEIVEDATA_H_INCLUDED + +/* Reads data from the specified socket. + * Returns the number of bytes read if successful, zero if no bytes were + * read or if we timed out. Returns negative if there was an error. */ +int receivedata(int socket, +                char * data, int length, +                int timeout, unsigned int * scope_id); + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h b/ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h new file mode 100644 index 00000000..22eda5e3 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h @@ -0,0 +1,348 @@ +/* $Id: upnpcommands.h,v 1.31 2015/07/21 13:16:55 nanard Exp $ */ +/* Miniupnp project : http://miniupnp.free.fr/ + * Author : Thomas Bernard + * Copyright (c) 2005-2015 Thomas Bernard + * This software is subject to the conditions detailed in the + * LICENCE file provided within this distribution */ +#ifndef UPNPCOMMANDS_H_INCLUDED +#define UPNPCOMMANDS_H_INCLUDED + +#include "upnpreplyparse.h" +#include "portlistingparse.h" +#include "miniupnpc_declspec.h" +#include "miniupnpctypes.h" + +/* MiniUPnPc return codes : */ +#define UPNPCOMMAND_SUCCESS (0) +#define UPNPCOMMAND_UNKNOWN_ERROR (-1) +#define UPNPCOMMAND_INVALID_ARGS (-2) +#define UPNPCOMMAND_HTTP_ERROR (-3) +#define UPNPCOMMAND_INVALID_RESPONSE (-4) +#define UPNPCOMMAND_MEM_ALLOC_ERROR (-5) + +#ifdef __cplusplus +extern "C" { +#endif + +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalBytesSent(const char * controlURL, +					const char * servicetype); + +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalBytesReceived(const char * controlURL, +						const char * servicetype); + +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalPacketsSent(const char * controlURL, +					const char * servicetype); + +MINIUPNP_LIBSPEC UNSIGNED_INTEGER +UPNP_GetTotalPacketsReceived(const char * controlURL, +					const char * servicetype); + +/* UPNP_GetStatusInfo() + * status and lastconnerror are 64 byte buffers + * Return values : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error code */ +MINIUPNP_LIBSPEC int +UPNP_GetStatusInfo(const char * controlURL, +			       const char * servicetype, +				   char * status, +				   unsigned int * uptime, +                   char * lastconnerror); + +/* UPNP_GetConnectionTypeInfo() + * argument connectionType is a 64 character buffer + * Return Values : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error code */ +MINIUPNP_LIBSPEC int +UPNP_GetConnectionTypeInfo(const char * controlURL, +                           const char * servicetype, +						   char * connectionType); + +/* UPNP_GetExternalIPAddress() call the corresponding UPNP method. + * if the third arg is not null the value is copied to it. + * at least 16 bytes must be available + * + * Return values : + * 0 : SUCCESS + * NON ZERO : ERROR Either an UPnP error code or an unknown error. + * + * possible UPnP Errors : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. */ +MINIUPNP_LIBSPEC int +UPNP_GetExternalIPAddress(const char * controlURL, +                          const char * servicetype, +                          char * extIpAdd); + +/* UPNP_GetLinkLayerMaxBitRates() + * call WANCommonInterfaceConfig:1#GetCommonLinkProperties + * + * return values : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error Code. */ +MINIUPNP_LIBSPEC int +UPNP_GetLinkLayerMaxBitRates(const char* controlURL, +							const char* servicetype, +							unsigned int * bitrateDown, +							unsigned int * bitrateUp); + +/* UPNP_AddPortMapping() + * if desc is NULL, it will be defaulted to "libminiupnpc" + * remoteHost is usually NULL because IGD don't support it. + * + * Return values : + * 0 : SUCCESS + * NON ZERO : ERROR. Either an UPnP error code or an unknown error. + * + * List of possible UPnP errors for AddPortMapping : + * errorCode errorDescription (short) - Description (long) + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization and + *                             the sender was not authorized. + * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be + *                                   wild-carded + * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded + * 718 ConflictInMappingEntry - The port mapping entry specified conflicts + *                     with a mapping assigned previously to another client + * 724 SamePortValuesRequired - Internal and External port values + *                              must be the same + * 725 OnlyPermanentLeasesSupported - The NAT implementation only supports + *                  permanent lease times on port mappings + * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard + *                             and cannot be a specific IP address or DNS name + * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and + *                                        cannot be a specific port value + * 728 NoPortMapsAvailable - There are not enough free ports available to + *                           complete port mapping. + * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed + *                                   due to conflict with other mechanisms. + * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded + */ +MINIUPNP_LIBSPEC int +UPNP_AddPortMapping(const char * controlURL, const char * servicetype, +		    const char * extPort, +		    const char * inPort, +		    const char * inClient, +		    const char * desc, +		    const char * proto, +		    const char * remoteHost, +		    const char * leaseDuration); + +/* UPNP_AddAnyPortMapping() + * if desc is NULL, it will be defaulted to "libminiupnpc" + * remoteHost is usually NULL because IGD don't support it. + * + * Return values : + * 0 : SUCCESS + * NON ZERO : ERROR. Either an UPnP error code or an unknown error. + * + * List of possible UPnP errors for AddPortMapping : + * errorCode errorDescription (short) - Description (long) + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization and + *                             the sender was not authorized. + * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be + *                                   wild-carded + * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded + * 728 NoPortMapsAvailable - There are not enough free ports available to + *                           complete port mapping. + * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed + *                                   due to conflict with other mechanisms. + * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded + */ +MINIUPNP_LIBSPEC int +UPNP_AddAnyPortMapping(const char * controlURL, const char * servicetype, +		       const char * extPort, +		       const char * inPort, +		       const char * inClient, +		       const char * desc, +		       const char * proto, +		       const char * remoteHost, +		       const char * leaseDuration, +		       char * reservedPort); + +/* UPNP_DeletePortMapping() + * Use same argument values as what was used for AddPortMapping(). + * remoteHost is usually NULL because IGD don't support it. + * Return Values : + * 0 : SUCCESS + * NON ZERO : error. Either an UPnP error code or an undefined error. + * + * List of possible UPnP errors for DeletePortMapping : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + *                             and the sender was not authorized. + * 714 NoSuchEntryInArray - The specified value does not exist in the array */ +MINIUPNP_LIBSPEC int +UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, +		       const char * extPort, const char * proto, +		       const char * remoteHost); + +/* UPNP_DeletePortRangeMapping() + * Use same argument values as what was used for AddPortMapping(). + * remoteHost is usually NULL because IGD don't support it. + * Return Values : + * 0 : SUCCESS + * NON ZERO : error. Either an UPnP error code or an undefined error. + * + * List of possible UPnP errors for DeletePortMapping : + * 606 Action not authorized - The action requested REQUIRES authorization + *                             and the sender was not authorized. + * 730 PortMappingNotFound - This error message is returned if no port + *			     mapping is found in the specified range. + * 733 InconsistentParameters - NewStartPort and NewEndPort values are not consistent. */ +MINIUPNP_LIBSPEC int +UPNP_DeletePortMappingRange(const char * controlURL, const char * servicetype, +        		    const char * extPortStart, const char * extPortEnd, +        		    const char * proto, +        		    const char * manage); + +/* UPNP_GetPortMappingNumberOfEntries() + * not supported by all routers */ +MINIUPNP_LIBSPEC int +UPNP_GetPortMappingNumberOfEntries(const char* controlURL, +                                   const char* servicetype, +                                   unsigned int * num); + +/* UPNP_GetSpecificPortMappingEntry() + *    retrieves an existing port mapping + * params : + *  in   extPort + *  in   proto + *  in   remoteHost + *  out  intClient (16 bytes) + *  out  intPort (6 bytes) + *  out  desc (80 bytes) + *  out  enabled (4 bytes) + *  out  leaseDuration (16 bytes) + * + * return value : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error Code. + * + * List of possible UPnP errors for _GetSpecificPortMappingEntry : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + *                             and the sender was not authorized. + * 714 NoSuchEntryInArray - The specified value does not exist in the array. + */ +MINIUPNP_LIBSPEC int +UPNP_GetSpecificPortMappingEntry(const char * controlURL, +                                 const char * servicetype, +                                 const char * extPort, +                                 const char * proto, +                                 const char * remoteHost, +                                 char * intClient, +                                 char * intPort, +                                 char * desc, +                                 char * enabled, +                                 char * leaseDuration); + +/* UPNP_GetGenericPortMappingEntry() + * params : + *  in   index + *  out  extPort (6 bytes) + *  out  intClient (16 bytes) + *  out  intPort (6 bytes) + *  out  protocol (4 bytes) + *  out  desc (80 bytes) + *  out  enabled (4 bytes) + *  out  rHost (64 bytes) + *  out  duration (16 bytes) + * + * return value : + * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR + * or a UPnP Error Code. + * + * Possible UPNP Error codes : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + *                             and the sender was not authorized. + * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds + */ +MINIUPNP_LIBSPEC int +UPNP_GetGenericPortMappingEntry(const char * controlURL, +                                const char * servicetype, +								const char * index, +								char * extPort, +								char * intClient, +								char * intPort, +								char * protocol, +								char * desc, +								char * enabled, +								char * rHost, +								char * duration); + +/* UPNP_GetListOfPortMappings()      Available in IGD v2 + * + * + * Possible UPNP Error codes : + * 606 Action not Authorized + * 730 PortMappingNotFound - no port mapping is found in the specified range. + * 733 InconsistantParameters - NewStartPort and NewEndPort values are not + *                              consistent. + */ +MINIUPNP_LIBSPEC int +UPNP_GetListOfPortMappings(const char * controlURL, +                           const char * servicetype, +                           const char * startPort, +                           const char * endPort, +                           const char * protocol, +                           const char * numberOfPorts, +                           struct PortMappingParserData * data); + +/* IGD:2, functions for service WANIPv6FirewallControl:1 */ +MINIUPNP_LIBSPEC int +UPNP_GetFirewallStatus(const char * controlURL, +				const char * servicetype, +				int * firewallEnabled, +				int * inboundPinholeAllowed); + +MINIUPNP_LIBSPEC int +UPNP_GetOutboundPinholeTimeout(const char * controlURL, const char * servicetype, +                    const char * remoteHost, +                    const char * remotePort, +                    const char * intClient, +                    const char * intPort, +                    const char * proto, +                    int * opTimeout); + +MINIUPNP_LIBSPEC int +UPNP_AddPinhole(const char * controlURL, const char * servicetype, +                    const char * remoteHost, +                    const char * remotePort, +                    const char * intClient, +                    const char * intPort, +                    const char * proto, +                    const char * leaseTime, +                    char * uniqueID); + +MINIUPNP_LIBSPEC int +UPNP_UpdatePinhole(const char * controlURL, const char * servicetype, +                    const char * uniqueID, +                    const char * leaseTime); + +MINIUPNP_LIBSPEC int +UPNP_DeletePinhole(const char * controlURL, const char * servicetype, const char * uniqueID); + +MINIUPNP_LIBSPEC int +UPNP_CheckPinholeWorking(const char * controlURL, const char * servicetype, +                                 const char * uniqueID, int * isWorking); + +MINIUPNP_LIBSPEC int +UPNP_GetPinholePackets(const char * controlURL, const char * servicetype, +                                 const char * uniqueID, int * packets); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/bin/miniupnpc/include/miniupnpc/upnperrors.h b/ext/bin/miniupnpc/include/miniupnpc/upnperrors.h new file mode 100644 index 00000000..3115aee5 --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/upnperrors.h @@ -0,0 +1,26 @@ +/* $Id: upnperrors.h,v 1.6 2015/07/21 13:16:55 nanard Exp $ */ +/* (c) 2007-2015 Thomas Bernard + * All rights reserved. + * MiniUPnP Project. + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * This software is subjet to the conditions detailed in the + * provided LICENCE file. */ +#ifndef UPNPERRORS_H_INCLUDED +#define UPNPERRORS_H_INCLUDED + +#include "miniupnpc_declspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* strupnperror() + * Return a string description of the UPnP error code + * or NULL for undefinded errors */ +MINIUPNP_LIBSPEC const char * strupnperror(int err); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/bin/miniupnpc/include/miniupnpc/upnpreplyparse.h b/ext/bin/miniupnpc/include/miniupnpc/upnpreplyparse.h new file mode 100644 index 00000000..6badd15b --- /dev/null +++ b/ext/bin/miniupnpc/include/miniupnpc/upnpreplyparse.h @@ -0,0 +1,63 @@ +/* $Id: upnpreplyparse.h,v 1.19 2014/10/27 16:33:19 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2006-2013 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ + +#ifndef UPNPREPLYPARSE_H_INCLUDED +#define UPNPREPLYPARSE_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +struct NameValue { +	struct NameValue * l_next; +	char name[64]; +	char value[128]; +}; + +struct NameValueParserData { +	struct NameValue * l_head; +	char curelt[64]; +	char * portListing; +	int portListingLength; +	int topelt; +	const char * cdata; +	int cdatalen; +}; + +/* ParseNameValue() */ +void +ParseNameValue(const char * buffer, int bufsize, +               struct NameValueParserData * data); + +/* ClearNameValueList() */ +void +ClearNameValueList(struct NameValueParserData * pdata); + +/* GetValueFromNameValueList() */ +char * +GetValueFromNameValueList(struct NameValueParserData * pdata, +                          const char * Name); + +#if 0 +/* GetValueFromNameValueListIgnoreNS() */ +char * +GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata, +                                  const char * Name); +#endif + +/* DisplayNameValueList() */ +#ifdef DEBUG +void +DisplayNameValueList(char * buffer, int bufsize); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ext/bin/miniupnpc/linux-arm32/libminiupnpc.a b/ext/bin/miniupnpc/linux-arm32/libminiupnpc.aBinary files differ new file mode 100644 index 00000000..4983f628 --- /dev/null +++ b/ext/bin/miniupnpc/linux-arm32/libminiupnpc.a diff --git a/ext/bin/miniupnpc/linux-x64/libminiupnpc.a b/ext/bin/miniupnpc/linux-x64/libminiupnpc.aBinary files differ new file mode 100644 index 00000000..270366e0 --- /dev/null +++ b/ext/bin/miniupnpc/linux-x64/libminiupnpc.a diff --git a/ext/bin/miniupnpc/linux-x86/libminiupnpc.a b/ext/bin/miniupnpc/linux-x86/libminiupnpc.aBinary files differ new file mode 100644 index 00000000..99cbef21 --- /dev/null +++ b/ext/bin/miniupnpc/linux-x86/libminiupnpc.a diff --git a/ext/bin/miniupnpc/mac-x64/libminiupnpc.a b/ext/bin/miniupnpc/mac-x64/libminiupnpc.aBinary files differ new file mode 100644 index 00000000..3c2e528d --- /dev/null +++ b/ext/bin/miniupnpc/mac-x64/libminiupnpc.a diff --git a/ext/bin/miniupnpc/windows-x64/miniupnpc.lib b/ext/bin/miniupnpc/windows-x64/miniupnpc.libBinary files differ new file mode 100644 index 00000000..e05fefc8 --- /dev/null +++ b/ext/bin/miniupnpc/windows-x64/miniupnpc.lib diff --git a/ext/bin/miniupnpc/windows-x86/miniupnpc.lib b/ext/bin/miniupnpc/windows-x86/miniupnpc.libBinary files differ new file mode 100644 index 00000000..a7fe4191 --- /dev/null +++ b/ext/bin/miniupnpc/windows-x86/miniupnpc.lib diff --git a/ext/installfiles/windows/ZeroTier One.aip b/ext/installfiles/windows/ZeroTier One.aip index ff7ee219..61755698 100644 --- a/ext/installfiles/windows/ZeroTier One.aip +++ b/ext/installfiles/windows/ZeroTier One.aip @@ -23,7 +23,7 @@      <ROW Property="CTRLS" Value="2"/>      <ROW Property="MSIFASTINSTALL" MultiBuildValue="DefaultBuild:2"/>      <ROW Property="Manufacturer" Value="ZeroTier, Inc."/> -    <ROW Property="ProductCode" Value="1033:{CEB9F664-D7D0-446A-BAB0-CDC553ADC137} " Type="16"/> +    <ROW Property="ProductCode" Value="1033:{C25B45D0-A473-44C1-A251-B72ED4E9C9FC} " Type="16"/>      <ROW Property="ProductLanguage" Value="1033"/>      <ROW Property="ProductName" Value="ZeroTier One"/>      <ROW Property="ProductVersion" Value="1.0.3" Type="32"/> @@ -87,8 +87,8 @@      <ROW File="react.min.js" Component_="index.html" FileName="REACTM~1.JS|react.min.js" Attributes="0" SourcePath="..\..\..\ui\react.min.js" SelfReg="false" NextFile="simpleajax.min.js"/>      <ROW File="simpleajax.min.js" Component_="index.html" FileName="SIMPLE~1.JS|simpleajax.min.js" Attributes="0" SourcePath="..\..\..\ui\simpleajax.min.js" SelfReg="false" NextFile="zerotier.css"/>      <ROW File="zerotier.css" Component_="index.html" FileName="zerotier.css" Attributes="0" SourcePath="..\..\..\ui\zerotier.css" SelfReg="false" NextFile="ztui.min.js"/> -    <ROW File="zerotierone_x64.exe" Component_="zerotierone_x64.exe" FileName="ZEROTI~2.EXE|zerotier-one_x64.exe" Attributes="0" SourcePath="..\..\..\windows\Build\x64\Release\zerotier-one_x64.exe" SelfReg="false" NextFile="ZeroTierOne.exe" DigSign="true"/> -    <ROW File="zerotierone_x86.exe" Component_="zerotierone_x86.exe" FileName="ZEROTI~1.EXE|zerotier-one_x86.exe" Attributes="0" SourcePath="..\..\..\windows\Build\Win32\Release\zerotier-one_x86.exe" SelfReg="false" NextFile="zerotierone_x64.exe" DigSign="true"/> +    <ROW File="zerotierone_x64.exe" Component_="zerotierone_x64.exe" FileName="ZEROTI~2.EXE|zerotier-one_x64.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\Build\x64\Release\zerotier-one_x64.exe" SelfReg="false" NextFile="ZeroTierOne.exe" DigSign="true"/> +    <ROW File="zerotierone_x86.exe" Component_="zerotierone_x86.exe" FileName="ZEROTI~1.EXE|zerotier-one_x86.exe" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\..\..\windows\Build\Win32\Release\zerotier-one_x86.exe" SelfReg="false" NextFile="zerotierone_x64.exe" DigSign="true"/>      <ROW File="zttap300.cat_2" Component_="zttap300.cat" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.cat" SelfReg="false" NextFile="zttap300.sys_2"/>      <ROW File="zttap300.cat_3" Component_="zttap300.cat_1" FileName="zttap300.cat" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x86\zttap300.cat" SelfReg="false" NextFile="zttap300.sys_3"/>      <ROW File="zttap300.inf" Component_="zttap300.cat" FileName="zttap300.inf" Attributes="0" SourcePath="..\..\bin\tap-windows-ndis6\x64\zttap300.inf" SelfReg="false" NextFile="zttap300.cat_3"/> diff --git a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib index 61dafbcc..dd67a86a 100644 --- a/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib +++ b/ext/mac-ui-macgap1-wrapper/src/MacGap/en.lproj/MainMenu.xib @@ -125,7 +125,7 @@  								</object>  								<object class="NSMenuItem" id="755159360">  									<reference key="NSMenu" ref="110575045"/> -									<string key="NSTitle">Hide MacGap</string> +									<string key="NSTitle">Hide ZeroTier One</string>  									<string key="NSKeyEquiv">h</string>  									<int key="NSKeyEquivModMask">1048576</int>  									<int key="NSMnemonicLoc">2147483647</int> diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 7ae524a8..8583aa3a 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -106,17 +106,6 @@ extern "C" {  #define ZT1_MAX_PEER_NETWORK_PATHS 4  /** - * Maximum number of revisions over which a network COM can differ and still be in-horizon (agree) - * - * This is the default max delta for the revision field in COMs issued - * by network controllers, and is defined here for documentation purposes. - * When a network is changed so as to de-authorize a member, its revision - * should be incremented by this number. Otherwise all other changes that - * materially affect the network should result in increment by one. - */ -#define ZT1_CERTIFICATE_OF_MEMBERSHIP_REVISION_MAX_DELTA 16 - -/**   * Feature flag: ZeroTier One was built to be thread-safe -- concurrent processXXX() calls are okay   */  #define ZT1_FEATURE_FLAG_THREAD_SAFE 0x00000001 @@ -978,11 +967,15 @@ void ZT1_Node_freeQueryResult(ZT1_Node *node,void *qr);   * Take care that these are never ZeroTier interface addresses, otherwise   * strange things might happen or they simply won't work.   * + * Addresses can also be added here if they are the result of a UPnP or + * NAT-PMP port mapping or other discovery or mapping means. + *   * This returns a boolean indicating whether or not the address was   * accepted. ZeroTier will only communicate over certain address types   * and (for IP) address classes. Thus it's safe to just dump your OS's   * entire remote IP list (excluding ZeroTier interface IPs) into here - * and let ZeroTier determine which addresses it will use. + * and let ZeroTier determine which addresses it will use. It will + * reject bad, empty, and unusable addresses.   *   * @param addr Local interface address   * @param metric Local interface metric diff --git a/make-linux.mk b/make-linux.mk index c56f3569..2ef9b985 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -18,8 +18,16 @@  #  # Automagically pick clang or gcc, with preference for clang -CC?=$(shell if [ -e /usr/bin/clang ]; then echo clang; else echo gcc; fi) -CXX?=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi) +# This is only done if we have not overridden these with an environment or CLI variable +ifeq ($(origin CC),default) +	CC=$(shell if [ -e /usr/bin/clang ]; then echo clang; else echo gcc; fi) +endif +ifeq ($(origin CXX),default) +	CXX=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi) +endif + +UNAME_M=$(shell uname -m) +  INCLUDES=  DEFS=  LDLIBS?= @@ -30,6 +38,29 @@ OBJS+=osdep/LinuxEthernetTap.o  # "make official" is a shortcut for this  ifeq ($(ZT_OFFICIAL_RELEASE),1)  	DEFS+=-DZT_OFFICIAL_RELEASE  +	ZT_USE_MINIUPNPC=1 +endif + +ifeq ($(ZT_USE_MINIUPNPC),1) +	DEFS+=-DZT_USE_MINIUPNPC +ifeq ($(UNAME_M),armv6l) +	MINIUPNPC_LIB=ext/bin/miniupnpc/linux-arm32/libminiupnpc.a +endif +ifeq ($(UNAME_M),armv7l) +	MINIUPNPC_LIB=ext/bin/miniupnpc/linux-arm32/libminiupnpc.a +endif +ifeq ($(UNAME_M),x86_64) +	MINIUPNPC_LIB=ext/bin/miniupnpc/linux-x64/libminiupnpc.a +endif +ifeq ($(UNAME_M),i386) +	MINIUPNPC_LIB=ext/bin/miniupnpc/linux-x86/libminiupnpc.a +endif +ifeq ($(UNAME_M),i686) +	MINIUPNPC_LIB=ext/bin/miniupnpc/linux-x86/libminiupnpc.a +endif +	MINIUPNPC_LIB?=-lminiupnpc +	LDLIBS+=$(MINIUPNPC_LIB) +	OBJS+=osdep/UPNPClient.o  endif  # Build with ZT_ENABLE_NETWORK_CONTROLLER=1 to build with the Sqlite network controller diff --git a/make-mac.mk b/make-mac.mk index 1bc842ce..c0b3f89d 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -1,13 +1,20 @@ -CC?=clang -CXX?=clang++ +ifeq ($(origin CC),default) +	CC=$(shell if [ -e /usr/bin/clang ]; then echo clang; else echo gcc; fi) +endif +ifeq ($(origin CXX),default) +	CXX=$(shell if [ -e /usr/bin/clang++ ]; then echo clang++; else echo g++; fi) +endif -INCLUDES=-I/usr/local/include +INCLUDES=  DEFS=  LIBS=  ARCH_FLAGS=-arch x86_64  include objects.mk -OBJS+=osdep/OSXEthernetTap.o  +OBJS+=osdep/OSXEthernetTap.o + +# Comment out to disable building against shipped libminiupnpc binary for Mac +ZT_USE_MINIUPNPC?=1  # Disable codesign since open source users will not have ZeroTier's certs  CODESIGN=echo @@ -17,7 +24,8 @@ CODESIGN_INSTALLER_CERT=  # For internal use only -- signs everything with ZeroTier's developer cert  ifeq ($(ZT_OFFICIAL_RELEASE),1) -	DEFS+=-DZT_OFFICIAL_RELEASE -DZT_AUTO_UPDATE  +	DEFS+=-DZT_OFFICIAL_RELEASE -DZT_AUTO_UPDATE +	ZT_USE_MINIUPNPC=1  	CODESIGN=codesign  	PRODUCTSIGN=productsign  	CODESIGN_APP_CERT="Developer ID Application: ZeroTier Networks LLC (8ZD9JUCZ4V)" @@ -25,19 +33,25 @@ ifeq ($(ZT_OFFICIAL_RELEASE),1)  endif  ifeq ($(ZT_AUTO_UPDATE),1) -	DEFS+=-DZT_AUTO_UPDATE  +	DEFS+=-DZT_AUTO_UPDATE +endif + +ifeq ($(ZT_USE_MINIUPNPC),1) +	DEFS+=-DZT_USE_MINIUPNPC +	LIBS+=ext/bin/miniupnpc/mac-x64/libminiupnpc.a +	OBJS+=osdep/UPNPClient.o  endif  # Build with ZT_ENABLE_NETWORK_CONTROLLER=1 to build with the Sqlite network controller  ifeq ($(ZT_ENABLE_NETWORK_CONTROLLER),1) -	DEFS+=-DZT_ENABLE_NETWORK_CONTROLLER  +	DEFS+=-DZT_ENABLE_NETWORK_CONTROLLER  	LIBS+=-L/usr/local/lib -lsqlite3 -	OBJS+=controller/SqliteNetworkController.o  +	OBJS+=controller/SqliteNetworkController.o  endif  # Debug mode -- dump trace output, build binary with -g  ifeq ($(ZT_DEBUG),1) -	DEFS+=-DZT_TRACE  +	DEFS+=-DZT_TRACE  	CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS)  	STRIP=echo  	# The following line enables optimization for the crypto code, since diff --git a/node/Constants.hpp b/node/Constants.hpp index d15fef13..b7aa9817 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -60,6 +60,13 @@  #include <endian.h>  #endif +// Disable type punning on ARM architecture -- some ARM chips throw SIGBUS on unaligned access +#if defined(__arm__) || defined(__ARMEL__) +#ifndef ZT_NO_TYPE_PUNNING +#define ZT_NO_TYPE_PUNNING +#endif +#endif +  #if defined(__FreeBSD__) || defined(__OpenBSD__)  #ifndef __UNIX_LIKE__  #define __UNIX_LIKE__ @@ -158,7 +165,7 @@  /**   * Maximum number of packet fragments we'll support - *  + *   * The actual spec allows 16, but this is the most we'll support right   * now. Packets with more than this many fragments are dropped.   */ @@ -216,7 +223,7 @@  /**   * Maximum number of ZT hops allowed (this is not IP hops/TTL) - *  + *   * The protocol allows up to 7, but we limit it to something smaller.   */  #define ZT_RELAY_MAX_HOPS 3 @@ -246,10 +253,10 @@  /**   * How frequently to send a zero-byte UDP keepalive packet   * - * There are NATs with timeouts as short as 30 seconds, so this turns out + * There are NATs with timeouts as short as 20 seconds, so this turns out   * to be needed.   */ -#define ZT_NAT_KEEPALIVE_DELAY 25000 +#define ZT_NAT_KEEPALIVE_DELAY 19000  /**   * Delay between scans of the topology active peer DB for peers that need ping @@ -296,6 +303,9 @@  /**   * Delay between initial direct NAT-t packet and more aggressive techniques + * + * This may also be a delay before sending the first packet if we determine + * that we should wait for the remote to initiate rendezvous first.   */  #define ZT_NAT_T_TACTICAL_ESCALATION_DELAY 1000 diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index ae99352e..b1fda8ef 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -392,28 +392,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p  					const unsigned int dictlen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN);  					const std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen);  					if (dict.length()) { -						if (nw->setConfiguration(Dictionary(dict)) == 2) { // 2 == accepted and actually new -							/* If this configuration was indeed new, we do another -							 * controller request with its revision. We do this in -							 * order to (a) tell the network controller we got it (it -							 * won't send a duplicate if ts == current), and (b) -							 * get another one if the controller is changing rapidly -							 * until we finally have the final version. -							 * -							 * Note that we don't do this for network controllers with -							 * versions <= 1.0.3, since those regenerate a new controller -							 * with a new revision every time. In that case this double -							 * confirmation would create a race condition. */ -							const SharedPtr<NetworkConfig> nc(nw->config2()); -							if ((peer->atLeastVersion(1,0,3))&&(nc)&&(nc->revision() > 0)) { -								Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST); -								outp.append((uint64_t)nw->id()); -								outp.append((uint16_t)0); // no meta-data -								outp.append((uint64_t)nc->revision()); -								outp.armor(peer->key(),true); -								RR->node->putPacket(_remoteAddress,outp.data(),outp.size()); -							} -						} +						nw->setConfiguration(Dictionary(dict));  						TRACE("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str());  					}  				} @@ -509,7 +488,7 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<  				InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);  				TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());  				peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP); -				RR->sw->contact(withPeer,atAddr); +				RR->sw->rendezvous(withPeer,atAddr);  			} else {  				TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",peer->address().toString().c_str(),_remoteAddress.toString().c_str());  			} @@ -692,6 +671,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons  		if (RR->localNetworkController) {  			Dictionary netconf;  			switch(RR->localNetworkController->doNetworkConfigRequest((h > 0) ? InetAddress() : _remoteAddress,RR->identity,peer->identity(),nwid,metaData,haveRevision,netconf)) { +  				case NetworkController::NETCONF_QUERY_OK: {  					const std::string netconfStr(netconf.toString());  					if (netconfStr.length() > 0xffff) { // sanity check since field ix 16-bit @@ -712,8 +692,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons  						}  					}  				}	break; -				case NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER: // nothing to do -- netconf has not changed -					break; +  				case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: {  					Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);  					outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST); @@ -723,6 +702,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons  					outp.armor(peer->key(),true);  					RR->node->putPacket(_remoteAddress,outp.data(),outp.size());  				}	break; +  				case NetworkController::NETCONF_QUERY_ACCESS_DENIED: {  					Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);  					outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST); @@ -732,12 +712,18 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons  					outp.armor(peer->key(),true);  					RR->node->putPacket(_remoteAddress,outp.data(),outp.size());  				} break; +  				case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR:  					TRACE("NETWORK_CONFIG_REQUEST failed: internal error: %s",netconf.get("error","(unknown)").c_str());  					break; + +				case NetworkController::NETCONF_QUERY_IGNORE: +					break; +  				default:  					TRACE("NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest()");  					break; +  			}  		} else {  			Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR); diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 91bfbed6..1942c4cd 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -74,7 +74,7 @@ InetAddress::IpScope InetAddress::ipScope() const  					if ((ip & 0xfff00000) == 0xac100000) return IP_SCOPE_PRIVATE;       // 172.16.0.0/12  					break;  				case 0xc0: -					if ((ip & 0xffff0000) == 0xc9a80000) return IP_SCOPE_PRIVATE;				// 192.168.0.0/16 +					if ((ip & 0xffff0000) == 0xc0a80000) return IP_SCOPE_PRIVATE;				// 192.168.0.0/16  					break;  				case 0xff: return IP_SCOPE_NONE;                                      // 255.0.0.0/8 (broadcast, or unused/unusable)  				default: diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp index 33424e4a..489c170b 100644 --- a/node/Multicaster.cpp +++ b/node/Multicaster.cpp @@ -211,9 +211,11 @@ void Multicaster::send(  		unsigned int count = 0;  		for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) { -			out.sendOnly(RR,*ast); -			if (++count >= limit) -				break; +			if (*ast != RR->identity.address()) { +				out.sendOnly(RR,*ast); +				if (++count >= limit) +					break; +			}  		}  		unsigned long idx = 0; @@ -264,9 +266,11 @@ void Multicaster::send(  		unsigned int count = 0;  		for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) { -			out.sendAndLog(RR,*ast); -			if (++count >= limit) -				break; +			if (*ast != RR->identity.address()) { +				out.sendAndLog(RR,*ast); +				if (++count >= limit) +					break; +			}  		}  		unsigned long idx = 0; diff --git a/node/Network.cpp b/node/Network.cpp index adc8e1b8..549219d7 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -38,6 +38,8 @@  #include "Buffer.hpp"  #include "NetworkController.hpp" +#include "../version.h" +  namespace ZeroTier {  const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0); @@ -255,9 +257,18 @@ void Network::requestConfiguration()  	}  	TRACE("requesting netconf for network %.16llx from controller %s",(unsigned long long)_id,controller().toString().c_str()); + +	// TODO: in the future we will include things like join tokens here, etc. +	Dictionary metaData; +	metaData.setHex(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,ZEROTIER_ONE_VERSION_MAJOR); +	metaData.setHex(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,ZEROTIER_ONE_VERSION_MINOR); +	metaData.setHex(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,ZEROTIER_ONE_VERSION_REVISION); +	std::string mds(metaData.toString()); +  	Packet outp(controller(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);  	outp.append((uint64_t)_id); -	outp.append((uint16_t)0); // no meta-data +	outp.append((uint16_t)mds.length()); +	outp.append((const void *)mds.data(),(unsigned int)mds.length());  	{  		Mutex::Lock _l(_lock);  		if (_config) diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index ba4d338b..7898646c 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -47,7 +47,6 @@ SharedPtr<NetworkConfig> NetworkConfig::createTestNetworkConfig(const Address &s  	nc->_private = false;  	nc->_enableBroadcast = true;  	nc->_name = "ZT_TEST_NETWORK"; -	nc->_description = "Built-in dummy test network";  	// Make up a V4 IP from 'self' in the 10.0.0.0/8 range -- no  	// guarantee of uniqueness but collisions are unlikely. @@ -111,7 +110,6 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)  	_name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME);  	if (_name.length() > ZT1_MAX_NETWORK_SHORT_NAME_LENGTH)  		throw std::invalid_argument("network short name too long (max: 255 characters)"); -	_description = d.get(ZT_NETWORKCONFIG_DICT_KEY_DESC,std::string());  	// In dictionary IPs are split into V4 and V6 addresses, but we don't really  	// need that so merge them here. @@ -132,26 +130,22 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)  			case AF_INET:  				if ((!addr.netmaskBits())||(addr.netmaskBits() > 32))  					continue; -				else if (addr.isNetwork()) { -					// TODO: add route to network -- this is a route without an IP assignment -					continue; -				}  				break;  			case AF_INET6:  				if ((!addr.netmaskBits())||(addr.netmaskBits() > 128))  					continue; -				else if (addr.isNetwork()) { -					// TODO: add route to network -- this is a route without an IP assignment -					continue; -				}  				break;  			default: // ignore unrecognized address types or junk/empty fields  				continue;  		} -		_staticIps.push_back(addr); +		if (addr.isNetwork()) +			_localRoutes.push_back(addr); +		else _staticIps.push_back(addr);  	} -	if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) -		throw std::invalid_argument("too many ZT-assigned IP addresses or routes"); +	if (_localRoutes.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) throw std::invalid_argument("too many ZT-assigned routes"); +	if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) throw std::invalid_argument("too many ZT-assigned IP addresses"); +	std::sort(_localRoutes.begin(),_localRoutes.end()); +	_localRoutes.erase(std::unique(_localRoutes.begin(),_localRoutes.end()),_localRoutes.end());  	std::sort(_staticIps.begin(),_staticIps.end());  	_staticIps.erase(std::unique(_staticIps.begin(),_staticIps.end()),_staticIps.end()); @@ -201,7 +195,7 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const  	if (_private != nc._private) return false;  	if (_enableBroadcast != nc._enableBroadcast) return false;  	if (_name != nc._name) return false; -	if (_description != nc._description) return false; +	if (_localRoutes != nc._localRoutes) return false;  	if (_staticIps != nc._staticIps) return false;  	if (_gateways != nc._gateways) return false;  	if (_activeBridges != nc._activeBridges) return false; @@ -211,4 +205,3 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const  }  } // namespace ZeroTier - diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index 5c7cdd7c..6111e65b 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -47,59 +47,48 @@  namespace ZeroTier { +// Fields for meta-data sent with network config requests +#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION "majv" +#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION "minv" +#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION "revv" +  // These dictionary keys are short so they don't take up much room in  // netconf response packets.  // integer(hex)[,integer(hex),...]  #define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et" -  // network ID  #define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid" -  // integer(hex)  #define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts" -  // integer(hex)  #define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r" -  // address of member  #define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id" -  // integer(hex)  #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml" -  // 0/1  #define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p" -  // text  #define ZT_NETWORKCONFIG_DICT_KEY_NAME "n" -  // text  #define ZT_NETWORKCONFIG_DICT_KEY_DESC "d" -  // IP/bits[,IP/bits,...]  // Note that IPs that end in all zeroes are routes with no assignment in them.  #define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s" -  // IP/bits[,IP/bits,...]  // Note that IPs that end in all zeroes are routes with no assignment in them.  #define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s" -  // serialized CertificateOfMembership  #define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com" -  // 0/1  #define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb" -  // 0/1  #define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb" -  // node[,node,...]  #define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab" -  // node;IP/port[,node;IP/port]  #define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl" -  // IP/metric[,IP/metric,...]  #define ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS "gw" @@ -158,7 +147,7 @@ public:  	inline bool isPublic() const throw() { return (!_private); }  	inline bool isPrivate() const throw() { return _private; }  	inline const std::string &name() const throw() { return _name; } -	inline const std::string &description() const throw() { return _description; } +	inline const std::vector<InetAddress> &localRoutes() const throw() { return _localRoutes; }  	inline const std::vector<InetAddress> &staticIps() const throw() { return _staticIps; }  	inline const std::vector<InetAddress> &gateways() const throw() { return _gateways; }  	inline const std::vector<Address> &activeBridges() const throw() { return _activeBridges; } @@ -194,7 +183,7 @@ private:  	bool _private;  	bool _enableBroadcast;  	std::string _name; -	std::string _description; +	std::vector<InetAddress> _localRoutes;  	std::vector<InetAddress> _staticIps;  	std::vector<InetAddress> _gateways;  	std::vector<Address> _activeBridges; @@ -207,4 +196,3 @@ private:  } // namespace ZeroTier  #endif - diff --git a/node/NetworkController.hpp b/node/NetworkController.hpp index 265ee3d4..ee481a62 100644 --- a/node/NetworkController.hpp +++ b/node/NetworkController.hpp @@ -52,10 +52,10 @@ public:  	enum ResultCode  	{  		NETCONF_QUERY_OK = 0, -		NETCONF_QUERY_OK_BUT_NOT_NEWER = 1, -		NETCONF_QUERY_OBJECT_NOT_FOUND = 2, -		NETCONF_QUERY_ACCESS_DENIED = 3, -		NETCONF_QUERY_INTERNAL_SERVER_ERROR = 4 +		NETCONF_QUERY_OBJECT_NOT_FOUND = 1, +		NETCONF_QUERY_ACCESS_DENIED = 2, +		NETCONF_QUERY_INTERNAL_SERVER_ERROR = 3, +		NETCONF_QUERY_IGNORE = 4  	};  	NetworkController() {} diff --git a/node/Node.cpp b/node/Node.cpp index ebe0527e..d40ceab9 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -316,6 +316,7 @@ ZT1_ResultCode Node::leave(uint64_t nwid)  	for(std::vector< std::pair< uint64_t,SharedPtr<Network> > >::const_iterator n(_networks.begin());n!=_networks.end();++n) {  		if (n->first != nwid)  			newn.push_back(*n); +		else n->second->destroy();  	}  	_networks.swap(newn);  	return ZT1_RESULT_OK; diff --git a/node/Peer.cpp b/node/Peer.cpp index 73c20228..3cf0ec4e 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -33,6 +33,7 @@  #include "Switch.hpp"  #include "Network.hpp"  #include "AntiRecursion.hpp" +#include "SelfAwareness.hpp"  #include <algorithm> @@ -225,10 +226,11 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now)  void Peer::pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_t now,bool force)  { -	if ((((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force))) { +	if (((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force)) {  		_lastDirectPathPush = now;  		std::vector<Path> dps(RR->node->directPaths()); +  #ifdef ZT_TRACE  		{  			std::string ps; diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp index 00015788..716cf7f3 100644 --- a/node/SelfAwareness.cpp +++ b/node/SelfAwareness.cpp @@ -147,4 +147,19 @@ void SelfAwareness::clean(uint64_t now)  	}  } +bool SelfAwareness::areGlobalIPv4PortsRandomized() const +{ +	int port = 0; +	Mutex::Lock _l(_phy_m); +	for(std::map< PhySurfaceKey,PhySurfaceEntry >::const_iterator p(_phy.begin());p!=_phy.end();++p) { +		if ((p->first.scope == InetAddress::IP_SCOPE_GLOBAL)&&(p->second.mySurface.ss_family == AF_INET)) { +			const int tmp = (int)p->second.mySurface.port(); +			if ((port)&&(tmp != port)) +				return true; +			else port = tmp; +		} +	} +	return false; +} +  } // namespace ZeroTier diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 4780fa5b..d3b79d18 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -29,6 +29,7 @@  #define ZT_SELFAWARENESS_HPP  #include <map> +#include <vector>  #include "InetAddress.hpp"  #include "Address.hpp" @@ -65,6 +66,11 @@ public:  	 */  	void clean(uint64_t now); +	/** +	 * @return True if our external (global scope) IPv4 ports appear to be randomized by a NAT device +	 */ +	bool areGlobalIPv4PortsRandomized() const; +  private:  	struct PhySurfaceKey  	{ diff --git a/node/Switch.cpp b/node/Switch.cpp index cf4fe249..989f497a 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -43,6 +43,7 @@  #include "Topology.hpp"  #include "Peer.hpp"  #include "AntiRecursion.hpp" +#include "SelfAwareness.hpp"  #include "Packet.hpp"  namespace ZeroTier { @@ -385,15 +386,11 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)  	return true;  } -void Switch::contact(const SharedPtr<Peer> &peer,const InetAddress &atAddr) +void Switch::rendezvous(const SharedPtr<Peer> &peer,const InetAddress &atAddr)  {  	TRACE("sending NAT-t message to %s(%s)",peer->address().toString().c_str(),atAddr.toString().c_str());  	const uint64_t now = RR->node->now(); - -	// Attempt to contact directly  	peer->attemptToContactAt(RR,atAddr,now); - -	// If we have not punched through after this timeout, open refreshing can of whupass  	{  		Mutex::Lock _l(_contactQueue_m);  		_contactQueue.push_back(ContactQueueEntry(peer,now + ZT_NAT_T_TACTICAL_ESCALATION_DELAY,atAddr)); @@ -451,35 +448,26 @@ unsigned long Switch::doTimerTasks(uint64_t now)  {  	unsigned long nextDelay = 0xffffffff; // ceiling delay, caller will cap to minimum -	{ // Aggressive NAT traversal time! +	{	// Iterate through NAT traversal strategies for entries in contact queue  		Mutex::Lock _l(_contactQueue_m);  		for(std::list<ContactQueueEntry>::iterator qi(_contactQueue.begin());qi!=_contactQueue.end();) {  			if (now >= qi->fireAtTime) { -				if (qi->peer->hasActiveDirectPath(now)) { -					// We've successfully NAT-t'd, so cancel attempt +				if ((!qi->peer->alive(now))||(qi->peer->hasActiveDirectPath(now))) { +					// Cancel attempt if we've already connected or peer is no longer "alive"  					_contactQueue.erase(qi++);  					continue;  				} else { -					// Nope, nothing yet. Time to kill some kittens.  					if (qi->strategyIteration == 0) { -						// First strategy: send packet directly (we already tried this but try again) +						// First strategy: send packet directly to destination  						qi->peer->attemptToContactAt(RR,qi->inaddr,now); -					} else if (qi->strategyIteration <= 9) { -						// Strategies 1-9: try escalating ports +					} else if (qi->strategyIteration <= 4) { +						// Strategies 1-4: try escalating ports for symmetric NATs that remap sequentially  						InetAddress tmpaddr(qi->inaddr);  						int p = (int)qi->inaddr.port() + qi->strategyIteration;  						if (p < 0xffff) {  							tmpaddr.setPort((unsigned int)p);  							qi->peer->attemptToContactAt(RR,tmpaddr,now); -						} else qi->strategyIteration = 9; -					} else if (qi->strategyIteration <= 18) { -						// Strategies 10-18: try ports below -						InetAddress tmpaddr(qi->inaddr); -						int p = (int)qi->inaddr.port() - (qi->strategyIteration - 9); -						if (p >= 1024) { -							tmpaddr.setPort((unsigned int)p); -							qi->peer->attemptToContactAt(RR,tmpaddr,now); -						} else qi->strategyIteration = 18; +						} else qi->strategyIteration = 5;  					} else {  						// All strategies tried, expire entry  						_contactQueue.erase(qi++); diff --git a/node/Switch.hpp b/node/Switch.hpp index e7f1523a..ac85606e 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -136,12 +136,12 @@ public:  	bool unite(const Address &p1,const Address &p2,bool force);  	/** -	 * Send NAT traversal messages to peer at the given candidate address +	 * Attempt NAT traversal to peer at a given physical address  	 *  	 * @param peer Peer to contact  	 * @param atAddr Address of peer  	 */ -	void contact(const SharedPtr<Peer> &peer,const InetAddress &atAddr); +	void rendezvous(const SharedPtr<Peer> &peer,const InetAddress &atAddr);  	/**  	 * Request WHOIS on a given address diff --git a/node/Topology.hpp b/node/Topology.hpp index c878bcc6..1c5cca00 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -86,7 +86,7 @@ public:  	/**  	 * Get a peer from its address -	 *  +	 *  	 * @param zta ZeroTier address of peer  	 * @return Peer or NULL if not found  	 */ @@ -103,7 +103,7 @@ public:  	/**  	 * Get the current favorite root server -	 *  +	 *  	 * @return Root server with lowest latency or NULL if none  	 */  	inline SharedPtr<Peer> getBestRoot() @@ -113,11 +113,11 @@ public:  	/**  	 * Get the best root server, avoiding root servers listed in an array -	 *  +	 *  	 * This will get the best root server (lowest latency, etc.) but will  	 * try to avoid the listed root servers, only using them if no others  	 * are available. -	 *  +	 *  	 * @param avoid Nodes to avoid  	 * @param avoidCount Number of nodes to avoid  	 * @param strictAvoid If false, consider avoided root servers anyway if no non-avoid root servers are available @@ -256,7 +256,23 @@ static int cli(int argc,char **argv)  	requestHeaders["X-ZT1-Auth"] = authToken; -	if ((command == "info")||(command == "status")) { +	if ((command.length() > 0)&&(command[0] == '/')) { +		unsigned int scode = Http::GET( +			1024 * 1024 * 16, +			60000, +			(const struct sockaddr *)&addr, +			command.c_str(), +			requestHeaders, +			responseHeaders, +			responseBody); +		if (scode == 200) { +			printf("%s",cliFixJsonCRs(responseBody).c_str()); +			return 0; +		} else { +			printf("%u %s %s"ZT_EOL_S,scode,command.c_str(),responseBody.c_str()); +			return 1; +		} +	} else if ((command == "info")||(command == "status")) {  		unsigned int scode = Http::GET(  			1024 * 1024 * 16,  			60000, @@ -363,7 +379,7 @@ static int cli(int argc,char **argv)  													else if ((!strcmp(jpath->u.object.values[kk].name,"active"))&&(jpath->u.object.values[kk].value->type == json_boolean))  														active = (jpath->u.object.values[kk].value->u.boolean != 0);  												} -												if (paddr) { +												if ((paddr)&&((active)||(fixed))) {  													int64_t now = (int64_t)OSUtils::now();  													if (lastSend > 0)  														lastSend = now - lastSend; diff --git a/osdep/Http.cpp b/osdep/Http.cpp index cd3cf137..d491b062 100644 --- a/osdep/Http.cpp +++ b/osdep/Http.cpp @@ -232,7 +232,7 @@ unsigned int Http::_do(  		handler.error = false;  		handler.done = false; -		Phy<HttpPhyHandler *> phy(&handler,true); +		Phy<HttpPhyHandler *> phy(&handler,true,true);  		bool instantConnect = false;  		handler.phy = &phy; diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index bfe9b68a..5de35eba 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -121,10 +121,10 @@ public:  	/**  	 * Set modes on a file to something secure -	 *  +	 *  	 * This locks a file so that only the owner can access it. What it actually  	 * does varies by platform. -	 *  +	 *  	 * @param path Path to lock  	 * @param isDir True if this is a directory  	 */ @@ -252,4 +252,3 @@ private:  } // namespace ZeroTier  #endif - diff --git a/osdep/Phy.hpp b/osdep/Phy.hpp index ec01625b..2ea68b9d 100644 --- a/osdep/Phy.hpp +++ b/osdep/Phy.hpp @@ -144,7 +144,7 @@ private:  	fd_set _readfds;  	fd_set _writefds;  #if defined(_WIN32) || defined(_WIN64) -	fd_set _exceptfds;	 +	fd_set _exceptfds;  #endif  	long _nfds; @@ -152,13 +152,15 @@ private:  	ZT_PHY_SOCKFD_TYPE _whackSendSocket;  	bool _noDelay; +	bool _noCheck;  public:  	/**  	 * @param handler Pointer of type HANDLER_PTR_TYPE to handler  	 * @param noDelay If true, disable TCP NAGLE algorithm on TCP sockets +	 * @param noCheck If true, attempt to set UDP SO_NO_CHECK option to disable sending checksums  	 */ -	Phy(HANDLER_PTR_TYPE handler,bool noDelay) : +	Phy(HANDLER_PTR_TYPE handler,bool noDelay,bool noCheck) :  		_handler(handler)  	{  		FD_ZERO(&_readfds); @@ -202,6 +204,7 @@ public:  		_whackReceiveSocket = pipes[0];  		_whackSendSocket = pipes[1];  		_noDelay = noDelay; +		_noCheck = noCheck;  	}  	~Phy() @@ -297,6 +300,11 @@ public:  #ifdef IP_MTU_DISCOVER  			f = 0; setsockopt(s,IPPROTO_IP,IP_MTU_DISCOVER,&f,sizeof(f));  #endif +#ifdef SO_NO_CHECK +			if (_noCheck) { +				f = 1; setsockopt(s,SOL_SOCKET,SO_NO_CHECK,(void *)&f,sizeof(f)); +			} +#endif  		}  #endif // Windows or not @@ -773,7 +781,7 @@ public:  		// Causes entry to be deleted from list in poll(), ignored elsewhere  		sws.type = ZT_PHY_SOCKET_CLOSED; -		if (sws.sock >= _nfds) { +		if ((long)sws.sock >= (long)_nfds) {  			long nfds = (long)_whackSendSocket;  			if ((long)_whackReceiveSocket > nfds)  				nfds = (long)_whackReceiveSocket; diff --git a/osdep/UPNPClient.cpp b/osdep/UPNPClient.cpp new file mode 100644 index 00000000..ceecb3a3 --- /dev/null +++ b/osdep/UPNPClient.cpp @@ -0,0 +1,198 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015  ZeroTier, Inc. + * + * 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/>. + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifdef ZT_USE_MINIUPNPC + +// Uncomment to dump debug messages +//#define ZT_UPNP_TRACE 1 + +// Uncomment to build a main() for ad-hoc testing +//#define ZT_UPNP_TEST 1 + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../node/Utils.hpp" +#include "UPNPClient.hpp" + +#ifdef __WINDOWS__ +#ifndef MINIUPNP_STATICLIB +#define MINIUPNP_STATICLIB +#endif +#endif + +#include "../ext/bin/miniupnpc/include/miniupnpc/miniupnpc.h" +#include "../ext/bin/miniupnpc/include/miniupnpc/upnpcommands.h" + +namespace ZeroTier { + +class UPNPClientImpl +{ +public: +	UPNPClientImpl(int localUdpPortToMap) : +		run(true), +		localPort(localUdpPortToMap) +	{ +	} + +	void threadMain() +		throw() +	{ +		char lanaddr[4096]; +		char externalip[4096]; // no range checking? so make these buffers larger than any UDP packet a uPnP server could send us as a precaution :P +		char inport[16]; +		char outport[16]; +		struct UPNPUrls urls; +		struct IGDdatas data; + +#ifdef ZT_UPNP_TRACE +		fprintf(stderr,"UPNPClient: started for UDP port %d"ZT_EOL_S,localPort); +#endif + +		unsigned int tryPortStart = 0; +		Utils::getSecureRandom(&tryPortStart,sizeof(tryPortStart)); +		tryPortStart = (tryPortStart % (65535 - 1025)) + 1025; + +		while (run) { +			{ +				int upnpError = 0; +				UPNPDev *devlist = upnpDiscover(2000,(const char *)0,(const char *)0,0,0,&upnpError); +				if (devlist) { +#ifdef ZT_UPNP_TRACE +					{ +						UPNPDev *dev = devlist; +						while (dev) { +							fprintf(stderr,"UPNPClient: found device at URL '%s': %s"ZT_EOL_S,dev->descURL,dev->st); +							dev = dev->pNext; +						} +					} +#endif + +					memset(lanaddr,0,sizeof(lanaddr)); +					memset(externalip,0,sizeof(externalip)); +					memset(&urls,0,sizeof(urls)); +					memset(&data,0,sizeof(data)); +					Utils::snprintf(inport,sizeof(inport),"%d",localPort); + +					if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) { +#ifdef ZT_UPNP_TRACE +						fprintf(stderr,"UPNPClient: my LAN IP address: %s"ZT_EOL_S,lanaddr); +#endif +						if ((UPNP_GetExternalIPAddress(urls.controlURL,data.first.servicetype,externalip) == UPNPCOMMAND_SUCCESS)&&(externalip[0])) { +#ifdef ZT_UPNP_TRACE +							fprintf(stderr,"UPNPClient: my external IP address: %s"ZT_EOL_S,externalip); +#endif + +							for(int tries=0;tries<64;++tries) { +								int tryPort = (int)tryPortStart + tries; +								if (tryPort >= 65535) +									tryPort = (tryPort - 65535) + 1025; +								Utils::snprintf(outport,sizeof(outport),"%u",tryPort); + +								int mapResult = 0; +								if ((mapResult = UPNP_AddPortMapping(urls.controlURL,data.first.servicetype,outport,inport,lanaddr,"ZeroTier","UDP",(const char *)0,ZT_UPNP_LEASE_DURATION)) == UPNPCOMMAND_SUCCESS) { +	#ifdef ZT_UPNP_TRACE +									fprintf(stderr,"UPNPClient: reserved external port: %s"ZT_EOL_S,outport); +	#endif +									{ +										Mutex::Lock sl(surface_l); +										surface.clear(); +										InetAddress tmp(externalip); +										tmp.setPort(tryPort); +										surface.push_back(tmp); +									} +									break; +								} else { +	#ifdef ZT_UPNP_TRACE +									fprintf(stderr,"UPNPClient: UPNP_AddAnyPortMapping(%s) failed: %d"ZT_EOL_S,outport,mapResult); +	#endif +									Thread::sleep(1000); +								} +							} +						} else { +#ifdef ZT_UPNP_TRACE +							fprintf(stderr,"UPNPClient: UPNP_GetExternalIPAddress failed"ZT_EOL_S); +#endif +						} +					} else { +#ifdef ZT_UPNP_TRACE +						fprintf(stderr,"UPNPClient: UPNP_GetValidIGD failed"ZT_EOL_S); +#endif +					} + +					freeUPNPDevlist(devlist); +				} else { +#ifdef ZT_UPNP_TRACE +					fprintf(stderr,"UPNPClient: upnpDiscover error code: %d"ZT_EOL_S,upnpError); +#endif +				} +			} + +#ifdef ZT_UPNP_TRACE +			fprintf(stderr,"UPNPClient: rescanning in %d ms"ZT_EOL_S,ZT_UPNP_CLIENT_REFRESH_DELAY); +#endif +			Thread::sleep(ZT_UPNP_CLIENT_REFRESH_DELAY); +		} +		delete this; +	} + +	volatile bool run; +	int localPort; +	Mutex surface_l; +	std::vector<InetAddress> surface; +}; + +UPNPClient::UPNPClient(int localUdpPortToMap) +{ +	_impl = new UPNPClientImpl(localUdpPortToMap); +	Thread::start(_impl); +} + +UPNPClient::~UPNPClient() +{ +	_impl->run = false; +} + +std::vector<InetAddress> UPNPClient::get() const +{ +	Mutex::Lock _l(_impl->surface_l); +	return _impl->surface; +} + +} // namespace ZeroTier + +#ifdef ZT_UPNP_TEST +int main(int argc,char **argv) +{ +	ZeroTier::UPNPClient *client = new ZeroTier::UPNPClient(12345); +	ZeroTier::Thread::sleep(0xffffffff); // wait forever +	return 0; +} +#endif + +#endif // ZT_USE_MINIUPNPC diff --git a/osdep/UPNPClient.hpp b/osdep/UPNPClient.hpp new file mode 100644 index 00000000..28b9979d --- /dev/null +++ b/osdep/UPNPClient.hpp @@ -0,0 +1,84 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015  ZeroTier, Inc. + * + * 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/>. + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +#ifndef ZT_UPNPCLIENT_HPP +#define ZT_UPNPCLIENT_HPP + +#ifdef ZT_USE_MINIUPNPC + +#include <vector> + +#include "../node/Constants.hpp" +#include "../node/InetAddress.hpp" +#include "../node/Mutex.hpp" +#include "Thread.hpp" + +/** + * How frequently should we refresh our UPNP/NAT-PnP/whatever state? + */ +#define ZT_UPNP_CLIENT_REFRESH_DELAY 600000 + +/** + * UPNP lease duration in seconds (as string) + */ +#define ZT_UPNP_LEASE_DURATION "3600" + +namespace ZeroTier { + +class UPNPClientImpl; + +/** + * UPnP/NAT-PnP daemon thread + */ +class UPNPClient +{ +	friend class UPNPClientImpl; + +public: +	/** +	 * Create and start UPNP client service +	 * +	 * @param localUdpPortToMap Port we want visible to the outside world +	 */ +	UPNPClient(int localUdpPortToMap); + +	~UPNPClient(); + +	/** +	 * @return All current external mappings for our port +	 */ +	std::vector<InetAddress> get() const; + +private: +	UPNPClientImpl *_impl; +}; + +} // namespace ZeroTier + +#endif // ZT_USE_MINIUPNPC + +#endif diff --git a/selftest.cpp b/selftest.cpp index cf20fdf3..714964cb 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -696,7 +696,7 @@ static int testPhy()  	std::cout << "[phy] Creating phy endpoint..." << std::endl;  	TestPhyHandlers testPhyHandlers; -	testPhyInstance = new Phy<TestPhyHandlers *>(&testPhyHandlers,false); +	testPhyInstance = new Phy<TestPhyHandlers *>(&testPhyHandlers,false,true);  	std::cout << "[phy] Binding UDP listen socket to 127.0.0.1/60002... ";  	PhySocket *udpListenSock = testPhyInstance->udpBind((const struct sockaddr *)&bindaddr); diff --git a/service/OneService.cpp b/service/OneService.cpp index d582a893..06e37a45 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -54,6 +54,7 @@  #include "../osdep/OSUtils.hpp"  #include "../osdep/Http.hpp"  #include "../osdep/BackgroundResolver.hpp" +#include "../osdep/UPNPClient.hpp"  #include "OneService.hpp"  #include "ControlPlane.hpp" @@ -404,7 +405,7 @@ public:  #ifdef ZT_ENABLE_NETWORK_CONTROLLER  		_controller((_homePath + ZT_PATH_SEPARATOR_S + ZT1_CONTROLLER_DB_PATH).c_str()),  #endif -		_phy(this,false), +		_phy(this,false,true),  		_overrideRootTopology((overrideRootTopology) ? overrideRootTopology : ""),  		_node((Node *)0),  		_controlPlane((ControlPlane *)0), @@ -415,6 +416,9 @@ public:  		_tcpFallbackTunnel((TcpConnection *)0),  		_termReason(ONE_STILL_RUNNING),  		_port(port), +#ifdef ZT_USE_MINIUPNPC +		_upnpClient((int)port), +#endif  		_run(true)  	{  		struct sockaddr_in in4; @@ -511,7 +515,7 @@ public:  			_lastRestart = clockShouldBe;  			uint64_t lastTapMulticastGroupCheck = 0;  			uint64_t lastTcpFallbackResolve = 0; -			uint64_t lastLocalInterfaceAddressCheck = 0; +			uint64_t lastLocalInterfaceAddressCheck = (OSUtils::now() - ZT1_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give UPnP time to configure and other things time to settle  #ifdef ZT_AUTO_UPDATE  			uint64_t lastSoftwareUpdateCheck = 0;  #endif // ZT_AUTO_UPDATE @@ -576,9 +580,16 @@ public:  							ztDevices.push_back(t->second->deviceName());  					} +					_node->clearLocalInterfaceAddresses(); + +#ifdef ZT_USE_MINIUPNPC +					std::vector<InetAddress> upnpAddresses(_upnpClient.get()); +					for(std::vector<InetAddress>::const_iterator ext(upnpAddresses.begin());ext!=upnpAddresses.end();++ext) +						_node->addLocalInterfaceAddress(reinterpret_cast<const struct sockaddr_storage *>(&(*ext)),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL); +#endif +  					struct ifaddrs *ifatbl = (struct ifaddrs *)0;  					if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) { -						_node->clearLocalInterfaceAddresses();  						struct ifaddrs *ifa = ifatbl;  						while (ifa) {  							if ((ifa->ifa_name)&&(ifa->ifa_addr)) { @@ -1242,6 +1253,10 @@ private:  	unsigned int _port; +#ifdef ZT_USE_MINIUPNPC +	UPNPClient _upnpClient; +#endif +  	bool _run;  	Mutex _run_m;  }; diff --git a/service/OneService.hpp b/service/OneService.hpp index 7964958c..7a4f7827 100644 --- a/service/OneService.hpp +++ b/service/OneService.hpp @@ -106,8 +106,6 @@ public:  	 * The terminate() method may be called from a signal handler or another  	 * thread to terminate execution. Otherwise this will not return unless  	 * another condition terminates execution such as a fatal error. -	 * -	 * @param   	 */  	virtual ReasonForTermination run() = 0; diff --git a/tcp-proxy/tcp-proxy.cpp b/tcp-proxy/tcp-proxy.cpp index 6acf7b42..70c0281a 100644 --- a/tcp-proxy/tcp-proxy.cpp +++ b/tcp-proxy/tcp-proxy.cpp @@ -297,7 +297,7 @@ int main(int argc,char **argv)  	srand(time((time_t *)0));  	TcpProxyService svc; -	Phy<TcpProxyService *> phy(&svc,false); +	Phy<TcpProxyService *> phy(&svc,false,true);  	svc.phy = &phy;  	svc.udpPortCounter = 1023; @@ -41,6 +41,6 @@  /**   * Revision   */ -#define ZEROTIER_ONE_VERSION_REVISION 3 +#define ZEROTIER_ONE_VERSION_REVISION 4  #endif diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index 554669b6..14bf7c3e 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -47,6 +47,7 @@      <ClCompile Include="..\..\osdep\BackgroundResolver.cpp" />      <ClCompile Include="..\..\osdep\Http.cpp" />      <ClCompile Include="..\..\osdep\OSUtils.cpp" /> +    <ClCompile Include="..\..\osdep\UPNPClient.cpp" />      <ClCompile Include="..\..\osdep\WindowsEthernetTap.cpp" />      <ClCompile Include="..\..\selftest.cpp">        <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> @@ -61,6 +62,22 @@      <ClCompile Include="ZeroTierOneService.cpp" />    </ItemGroup>    <ItemGroup> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\codelength.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\connecthostport.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\igd_desc_parse.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\minisoap.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\minissdpc.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniupnpc.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniupnpcstrings.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniupnpctypes.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniupnpc_declspec.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniwget.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\minixml.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\portlistingparse.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\receivedata.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\upnpcommands.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\upnperrors.h" /> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\upnpreplyparse.h" />      <ClInclude Include="..\..\ext\http-parser\http_parser.h" />      <ClInclude Include="..\..\ext\json-parser\json.h" />      <ClInclude Include="..\..\ext\lz4\lz4.h" /> @@ -108,6 +125,7 @@      <ClInclude Include="..\..\osdep\OSUtils.hpp" />      <ClInclude Include="..\..\osdep\Phy.hpp" />      <ClInclude Include="..\..\osdep\Thread.hpp" /> +    <ClInclude Include="..\..\osdep\UPNPClient.hpp" />      <ClInclude Include="..\..\osdep\WindowsEthernetTap.hpp" />      <ClInclude Include="..\..\service\ControlPlane.hpp" />      <ClInclude Include="..\..\service\ControlPlaneSubsystem.hpp" /> @@ -193,12 +211,13 @@        <WarningLevel>Level3</WarningLevel>        <Optimization>Disabled</Optimization>        <SDLCheck>true</SDLCheck> -      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include</AdditionalIncludeDirectories> -      <PreprocessorDefinitions>NOMINMAX;ZT_TRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <AdditionalIncludeDirectories> +      </AdditionalIncludeDirectories> +      <PreprocessorDefinitions>NOMINMAX;ZT_TRACE;ZT_USE_MINIUPNPC;%(PreprocessorDefinitions)</PreprocessorDefinitions>      </ClCompile>      <Link>        <GenerateDebugInformation>true</GenerateDebugInformation> -      <AdditionalDependencies>wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x86\miniupnpc.lib;wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>        <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>      </Link>    </ItemDefinitionGroup> @@ -207,12 +226,13 @@        <WarningLevel>Level3</WarningLevel>        <Optimization>Disabled</Optimization>        <SDLCheck>true</SDLCheck> -      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include</AdditionalIncludeDirectories> -      <PreprocessorDefinitions>NOMINMAX;ZT_TRACE;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <AdditionalIncludeDirectories> +      </AdditionalIncludeDirectories> +      <PreprocessorDefinitions>NOMINMAX;ZT_TRACE;ZT_USE_MINIUPNPC;%(PreprocessorDefinitions)</PreprocessorDefinitions>      </ClCompile>      <Link>        <GenerateDebugInformation>true</GenerateDebugInformation> -      <AdditionalDependencies>wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x64\miniupnpc.lib;wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>        <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>      </Link>    </ItemDefinitionGroup> @@ -223,8 +243,9 @@        <FunctionLevelLinking>true</FunctionLevelLinking>        <IntrinsicFunctions>true</IntrinsicFunctions>        <SDLCheck>true</SDLCheck> -      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include</AdditionalIncludeDirectories> -      <PreprocessorDefinitions>ZT_OFFICIAL_RELEASE;ZT_AUTO_UPDATE;ZT_SALSA20_SSE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <AdditionalIncludeDirectories> +      </AdditionalIncludeDirectories> +      <PreprocessorDefinitions>ZT_OFFICIAL_RELEASE;ZT_AUTO_UPDATE;ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>        <RuntimeLibrary>MultiThreaded</RuntimeLibrary>        <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>        <StringPooling>true</StringPooling> @@ -236,7 +257,7 @@        <GenerateDebugInformation>true</GenerateDebugInformation>        <EnableCOMDATFolding>true</EnableCOMDATFolding>        <OptimizeReferences>true</OptimizeReferences> -      <AdditionalDependencies>wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x86\miniupnpc.lib;wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>        <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>      </Link>    </ItemDefinitionGroup> @@ -247,8 +268,9 @@        <FunctionLevelLinking>true</FunctionLevelLinking>        <IntrinsicFunctions>true</IntrinsicFunctions>        <SDLCheck>true</SDLCheck> -      <AdditionalIncludeDirectories>$(SolutionDir)\ext\bin\libcrypto\include</AdditionalIncludeDirectories> -      <PreprocessorDefinitions>ZT_OFFICIAL_RELEASE;ZT_AUTO_UPDATE;ZT_SALSA20_SSE;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions> +      <AdditionalIncludeDirectories> +      </AdditionalIncludeDirectories> +      <PreprocessorDefinitions>ZT_OFFICIAL_RELEASE;ZT_AUTO_UPDATE;ZT_SALSA20_SSE;ZT_USE_MINIUPNPC;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>        <RuntimeLibrary>MultiThreaded</RuntimeLibrary>        <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>        <StringPooling>true</StringPooling> @@ -260,7 +282,7 @@        <GenerateDebugInformation>true</GenerateDebugInformation>        <EnableCOMDATFolding>true</EnableCOMDATFolding>        <OptimizeReferences>true</OptimizeReferences> -      <AdditionalDependencies>wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> +      <AdditionalDependencies>$(SolutionDir)..\ext\bin\miniupnpc\windows-x64\miniupnpc.lib;wsock32.lib;ws2_32.lib;newdev.lib;Iphlpapi.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>        <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>      </Link>    </ItemDefinitionGroup> diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index f36b5dc0..abaa8547 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -70,6 +70,15 @@      <Filter Include="Header Files\windows\ZeroTierOne">        <UniqueIdentifier>{bf604491-14c4-4a74-81a6-6105d07c5c7c}</UniqueIdentifier>      </Filter> +    <Filter Include="Header Files\ext\bin"> +      <UniqueIdentifier>{5939db69-ab17-47c6-97fb-185e2c678737}</UniqueIdentifier> +    </Filter> +    <Filter Include="Header Files\ext\bin\miniupnpc"> +      <UniqueIdentifier>{3666f510-b6da-47cb-8039-56441f2dac3e}</UniqueIdentifier> +    </Filter> +    <Filter Include="Header Files\ext\bin\miniupnpc\include"> +      <UniqueIdentifier>{1a47071e-e51b-4535-89ae-858946f03118}</UniqueIdentifier> +    </Filter>    </ItemGroup>    <ItemGroup>      <ClCompile Include="..\..\service\ControlPlane.cpp"> @@ -177,6 +186,9 @@      <ClCompile Include="..\..\osdep\BackgroundResolver.cpp">        <Filter>Source Files\osdep</Filter>      </ClCompile> +    <ClCompile Include="..\..\osdep\UPNPClient.cpp"> +      <Filter>Source Files\osdep</Filter> +    </ClCompile>    </ItemGroup>    <ItemGroup>      <ClInclude Include="resource.h"> @@ -347,6 +359,57 @@      <ClInclude Include="..\..\node\RemotePath.hpp">        <Filter>Header Files\node</Filter>      </ClInclude> +    <ClInclude Include="..\..\osdep\UPNPClient.hpp"> +      <Filter>Header Files\osdep</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\codelength.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\connecthostport.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\igd_desc_parse.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\minisoap.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\minissdpc.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniupnpc.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniupnpc_declspec.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniupnpcstrings.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniupnpctypes.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\miniwget.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\minixml.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\portlistingparse.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\receivedata.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\upnpcommands.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\upnperrors.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude> +    <ClInclude Include="..\..\ext\bin\miniupnpc\include\miniupnpc\upnpreplyparse.h"> +      <Filter>Header Files\ext\bin\miniupnpc\include</Filter> +    </ClInclude>    </ItemGroup>    <ItemGroup>      <ResourceCompile Include="ZeroTierOne.rc"> | 
