mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-01 18:56:41 +00:00
Merge branch 'adamierymenko-dev' into android-jni
This commit is contained in:
commit
1e8ead441c
@ -108,6 +108,7 @@ struct NetworkRecord {
|
||||
int multicastLimit;
|
||||
uint64_t creationTime;
|
||||
uint64_t revision;
|
||||
uint64_t memberRevisionCounter;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
@ -149,12 +150,13 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
|
||||
if (
|
||||
|
||||
/* Network */
|
||||
(sqlite3_prepare_v2(_db,"SELECT name,private,enableBroadcast,allowPassiveBridging,v4AssignMode,v6AssignMode,multicastLimit,creationTime,revision FROM Network WHERE id = ?",-1,&_sGetNetworkById,(const char **)0) != SQLITE_OK)
|
||||
(sqlite3_prepare_v2(_db,"SELECT name,private,enableBroadcast,allowPassiveBridging,v4AssignMode,v6AssignMode,multicastLimit,creationTime,revision,memberRevisionCounter FROM Network WHERE id = ?",-1,&_sGetNetworkById,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"SELECT revision FROM Network WHERE id = ?",-1,&_sGetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"UPDATE Network SET revision = ? WHERE id = ?",-1,&_sSetNetworkRevision,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"INSERT INTO Network (id,name,creationTime,revision) VALUES (?,?,?,1)",-1,&_sCreateNetwork,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"DELETE FROM Network WHERE id = ?",-1,&_sDeleteNetwork,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"SELECT id FROM Network ORDER BY id ASC",-1,&_sListNetworks,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"UPDATE Network SET memberRevisionCounter = (memberRevisionCounter + 1) WHERE id = ?",-1,&_sIncrementMemberRevisionCounter,(const char **)0) != SQLITE_OK)
|
||||
|
||||
/* Node */
|
||||
||(sqlite3_prepare_v2(_db,"SELECT identity FROM Node WHERE id = ?",-1,&_sGetNodeIdentity,(const char **)0) != SQLITE_OK)
|
||||
@ -188,12 +190,12 @@ SqliteNetworkController::SqliteNetworkController(const char *dbPath) :
|
||||
|
||||
/* Member */
|
||||
||(sqlite3_prepare_v2(_db,"SELECT rowid,authorized,activeBridge FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sGetMember,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,n.identity FROM Member AS m JOIN Node AS n ON n.id = m.nodeId WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"INSERT INTO Member (networkId,nodeId,authorized,activeBridge) VALUES (?,?,?,0)",-1,&_sCreateMember,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"SELECT m.authorized,m.activeBridge,m.memberRevision,n.identity FROM Member AS m JOIN Node AS n ON n.id = m.nodeId WHERE m.networkId = ? AND m.nodeId = ?",-1,&_sGetMember2,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"INSERT INTO Member (networkId,nodeId,authorized,activeBridge,memberRevision) VALUES (?,?,?,0,(SELECT memberRevisionCounter FROM Network WHERE id = ?))",-1,&_sCreateMember,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"SELECT nodeId FROM Member WHERE networkId = ? AND activeBridge > 0 AND authorized > 0",-1,&_sGetActiveBridges,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"SELECT m.nodeId FROM Member AS m WHERE m.networkId = ? ORDER BY m.nodeId ASC",-1,&_sListNetworkMembers,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ? WHERE rowid = ?",-1,&_sUpdateMemberAuthorized,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ? WHERE rowid = ?",-1,&_sUpdateMemberActiveBridge,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"UPDATE Member SET authorized = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberAuthorized,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"UPDATE Member SET activeBridge = ?,memberRevision = (SELECT memberRevisionCounter FROM Network WHERE id = ?) WHERE rowid = ?",-1,&_sUpdateMemberActiveBridge,(const char **)0) != SQLITE_OK)
|
||||
||(sqlite3_prepare_v2(_db,"DELETE FROM Member WHERE networkId = ? AND nodeId = ?",-1,&_sDeleteMember,(const char **)0) != SQLITE_OK)
|
||||
|
||||
/* Gateway */
|
||||
@ -251,6 +253,7 @@ SqliteNetworkController::~SqliteNetworkController()
|
||||
sqlite3_finalize(_sGetGateways);
|
||||
sqlite3_finalize(_sDeleteGateways);
|
||||
sqlite3_finalize(_sCreateGateway);
|
||||
sqlite3_finalize(_sIncrementMemberRevisionCounter);
|
||||
sqlite3_close(_db);
|
||||
}
|
||||
}
|
||||
@ -316,6 +319,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
|
||||
network.multicastLimit = sqlite3_column_int(_sGetNetworkById,6);
|
||||
network.creationTime = (uint64_t)sqlite3_column_int64(_sGetNetworkById,7);
|
||||
network.revision = (uint64_t)sqlite3_column_int64(_sGetNetworkById,8);
|
||||
network.memberRevisionCounter = (uint64_t)sqlite3_column_int64(_sGetNetworkById,9);
|
||||
} else return NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND;
|
||||
|
||||
// Fetch Member record
|
||||
@ -340,11 +344,16 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
|
||||
sqlite3_bind_text(_sCreateMember,1,network.id,16,SQLITE_STATIC);
|
||||
sqlite3_bind_text(_sCreateMember,2,member.nodeId,10,SQLITE_STATIC);
|
||||
sqlite3_bind_int(_sCreateMember,3,(member.authorized ? 1 : 0));
|
||||
sqlite3_bind_text(_sCreateMember,4,network.id,16,SQLITE_STATIC);
|
||||
if (sqlite3_step(_sCreateMember) != SQLITE_DONE) {
|
||||
netconf["error"] = "unable to create new member record";
|
||||
return NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
member.rowid = (int64_t)sqlite3_last_insert_rowid(_db);
|
||||
|
||||
sqlite3_reset(_sIncrementMemberRevisionCounter);
|
||||
sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,network.id,16,SQLITE_STATIC);
|
||||
sqlite3_step(_sIncrementMemberRevisionCounter);
|
||||
}
|
||||
|
||||
// Check member authorization
|
||||
@ -683,9 +692,14 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||
sqlite3_bind_text(_sCreateMember,1,nwids,16,SQLITE_STATIC);
|
||||
sqlite3_bind_text(_sCreateMember,2,addrs,10,SQLITE_STATIC);
|
||||
sqlite3_bind_int(_sCreateMember,3,0);
|
||||
sqlite3_bind_text(_sCreateMember,4,nwids,16,SQLITE_STATIC);
|
||||
if (sqlite3_step(_sCreateMember) != SQLITE_DONE)
|
||||
return 500;
|
||||
memberRowId = (int64_t)sqlite3_last_insert_rowid(_db);
|
||||
|
||||
sqlite3_reset(_sIncrementMemberRevisionCounter);
|
||||
sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC);
|
||||
sqlite3_step(_sIncrementMemberRevisionCounter);
|
||||
}
|
||||
|
||||
json_value *j = json_parse(body.c_str(),body.length());
|
||||
@ -697,17 +711,27 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||
if (j->u.object.values[k].value->type == json_boolean) {
|
||||
sqlite3_reset(_sUpdateMemberAuthorized);
|
||||
sqlite3_bind_int(_sUpdateMemberAuthorized,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
||||
sqlite3_bind_int64(_sUpdateMemberAuthorized,2,memberRowId);
|
||||
sqlite3_bind_text(_sUpdateMemberAuthorized,2,nwids,16,SQLITE_STATIC);
|
||||
sqlite3_bind_int64(_sUpdateMemberAuthorized,3,memberRowId);
|
||||
if (sqlite3_step(_sUpdateMemberAuthorized) != SQLITE_DONE)
|
||||
return 500;
|
||||
|
||||
sqlite3_reset(_sIncrementMemberRevisionCounter);
|
||||
sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC);
|
||||
sqlite3_step(_sIncrementMemberRevisionCounter);
|
||||
}
|
||||
} else if (!strcmp(j->u.object.values[k].name,"activeBridge")) {
|
||||
if (j->u.object.values[k].value->type == json_boolean) {
|
||||
sqlite3_reset(_sUpdateMemberActiveBridge);
|
||||
sqlite3_bind_int(_sUpdateMemberActiveBridge,1,(j->u.object.values[k].value->u.boolean == 0) ? 0 : 1);
|
||||
sqlite3_bind_int64(_sUpdateMemberActiveBridge,2,memberRowId);
|
||||
sqlite3_bind_text(_sUpdateMemberActiveBridge,2,nwids,16,SQLITE_STATIC);
|
||||
sqlite3_bind_int64(_sUpdateMemberActiveBridge,3,memberRowId);
|
||||
if (sqlite3_step(_sUpdateMemberActiveBridge) != SQLITE_DONE)
|
||||
return 500;
|
||||
|
||||
sqlite3_reset(_sIncrementMemberRevisionCounter);
|
||||
sqlite3_bind_text(_sIncrementMemberRevisionCounter,1,nwids,16,SQLITE_STATIC);
|
||||
sqlite3_step(_sIncrementMemberRevisionCounter);
|
||||
}
|
||||
} else if (!strcmp(j->u.object.values[k].name,"ipAssignments")) {
|
||||
if (j->u.object.values[k].value->type == json_array) {
|
||||
@ -778,6 +802,8 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||
uint64_t nwidOriginalPostfix = nwidPostfix;
|
||||
do {
|
||||
uint64_t tryNwid = nwidPrefix | nwidPostfix;
|
||||
if (!nwidPostfix)
|
||||
tryNwid |= 1;
|
||||
Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)tryNwid);
|
||||
|
||||
sqlite3_reset(_sGetNetworkRevision);
|
||||
@ -799,7 +825,7 @@ unsigned int SqliteNetworkController::handleControlPlaneHttpPOST(
|
||||
|
||||
sqlite3_reset(_sCreateNetwork);
|
||||
sqlite3_bind_text(_sCreateNetwork,1,nwids,16,SQLITE_STATIC);
|
||||
sqlite3_bind_text(_sCreateNetwork,2,nwids,16,SQLITE_STATIC); // default name, will be changed below if a name is specified in JSON
|
||||
sqlite3_bind_text(_sCreateNetwork,2,"",0,SQLITE_STATIC);
|
||||
sqlite3_bind_int64(_sCreateNetwork,3,(long long)OSUtils::now());
|
||||
if (sqlite3_step(_sCreateNetwork) != SQLITE_DONE)
|
||||
return 500;
|
||||
@ -1230,13 +1256,15 @@ unsigned int SqliteNetworkController::_doCPGet(
|
||||
"\t\"address\": \"%s\",\n"
|
||||
"\t\"authorized\": %s,\n"
|
||||
"\t\"activeBridge\": %s,\n"
|
||||
"\t\"memberRevision\": %llu,\n"
|
||||
"\t\"identity\": \"%s\",\n"
|
||||
"\t\"ipAssignments\": [",
|
||||
nwids,
|
||||
addrs,
|
||||
(sqlite3_column_int(_sGetMember2,0) > 0) ? "true" : "false",
|
||||
(sqlite3_column_int(_sGetMember2,1) > 0) ? "true" : "false",
|
||||
_jsonEscape((const char *)sqlite3_column_text(_sGetMember2,2)).c_str());
|
||||
(unsigned long long)sqlite3_column_int64(_sGetMember2,2),
|
||||
_jsonEscape((const char *)sqlite3_column_text(_sGetMember2,3)).c_str());
|
||||
responseBody = json;
|
||||
|
||||
sqlite3_reset(_sGetIpAssignmentsForNode2);
|
||||
@ -1333,6 +1361,7 @@ unsigned int SqliteNetworkController::_doCPGet(
|
||||
"\t\"multicastLimit\": %d,\n"
|
||||
"\t\"creationTime\": %llu,\n"
|
||||
"\t\"revision\": %llu,\n"
|
||||
"\t\"memberRevisionCounter\": %llu,\n"
|
||||
"\t\"members\": [",
|
||||
nwids,
|
||||
_jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,0)).c_str(),
|
||||
@ -1343,7 +1372,8 @@ unsigned int SqliteNetworkController::_doCPGet(
|
||||
_jsonEscape((const char *)sqlite3_column_text(_sGetNetworkById,5)).c_str(),
|
||||
sqlite3_column_int(_sGetNetworkById,6),
|
||||
(unsigned long long)sqlite3_column_int64(_sGetNetworkById,7),
|
||||
(unsigned long long)sqlite3_column_int64(_sGetNetworkById,8));
|
||||
(unsigned long long)sqlite3_column_int64(_sGetNetworkById,8),
|
||||
(unsigned long long)sqlite3_column_int64(_sGetNetworkById,9));
|
||||
responseBody = json;
|
||||
|
||||
sqlite3_reset(_sListNetworkMembers);
|
||||
|
@ -137,6 +137,7 @@ private:
|
||||
sqlite3_stmt *_sGetGateways;
|
||||
sqlite3_stmt *_sDeleteGateways;
|
||||
sqlite3_stmt *_sCreateGateway;
|
||||
sqlite3_stmt *_sIncrementMemberRevisionCounter;
|
||||
|
||||
Mutex _lock;
|
||||
};
|
||||
|
@ -13,7 +13,8 @@ CREATE TABLE Network (
|
||||
v6AssignMode varchar(8) NOT NULL DEFAULT('none'),
|
||||
multicastLimit integer NOT NULL DEFAULT(32),
|
||||
creationTime integer NOT NULL DEFAULT(0),
|
||||
revision integer NOT NULL DEFAULT(1)
|
||||
revision integer NOT NULL DEFAULT(1),
|
||||
memberRevisionCounter integer NOT NULL DEFAULT(1)
|
||||
);
|
||||
|
||||
CREATE TABLE Node (
|
||||
@ -57,10 +58,12 @@ CREATE TABLE Member (
|
||||
nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,
|
||||
authorized integer NOT NULL DEFAULT(0),
|
||||
activeBridge integer NOT NULL DEFAULT(0),
|
||||
memberRevision integer NOT NULL DEFAULT(0),
|
||||
PRIMARY KEY (networkId, nodeId)
|
||||
);
|
||||
|
||||
CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);
|
||||
CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision);
|
||||
|
||||
CREATE TABLE Relay (
|
||||
networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,
|
||||
|
@ -14,7 +14,8 @@
|
||||
" v6AssignMode varchar(8) NOT NULL DEFAULT('none'),\n"\
|
||||
" multicastLimit integer NOT NULL DEFAULT(32),\n"\
|
||||
" creationTime integer NOT NULL DEFAULT(0),\n"\
|
||||
" revision integer NOT NULL DEFAULT(1)\n"\
|
||||
" revision integer NOT NULL DEFAULT(1),\n"\
|
||||
" memberRevisionCounter integer NOT NULL DEFAULT(1)\n"\
|
||||
");\n"\
|
||||
"\n"\
|
||||
"CREATE TABLE Node (\n"\
|
||||
@ -58,10 +59,12 @@
|
||||
" nodeId char(10) NOT NULL REFERENCES Node(id) ON DELETE CASCADE,\n"\
|
||||
" authorized integer NOT NULL DEFAULT(0),\n"\
|
||||
" activeBridge integer NOT NULL DEFAULT(0),\n"\
|
||||
" memberRevision integer NOT NULL DEFAULT(0),\n"\
|
||||
" PRIMARY KEY (networkId, nodeId)\n"\
|
||||
");\n"\
|
||||
"\n"\
|
||||
"CREATE INDEX Member_networkId_activeBridge ON Member(networkId, activeBridge);\n"\
|
||||
"CREATE INDEX Member_networkId_memberRevision ON Member(networkId, memberRevision);\n"\
|
||||
"\n"\
|
||||
"CREATE TABLE Relay (\n"\
|
||||
" networkId char(16) NOT NULL REFERENCES Network(id) ON DELETE CASCADE,\n"\
|
||||
|
@ -73,7 +73,7 @@ extern "C" {
|
||||
*
|
||||
* If this does change, also change it in tap.h in the tuntaposx code under
|
||||
* mac-tap.
|
||||
*
|
||||
*
|
||||
* Overhead for a normal frame split into two packets:
|
||||
*
|
||||
* 1414 = 1444 (typical UDP MTU) - 28 (packet header) - 2 (ethertype)
|
||||
@ -987,10 +987,9 @@ void ZT1_Node_freeQueryResult(ZT1_Node *node,void *qr);
|
||||
* @param addr Local interface address
|
||||
* @param metric Local interface metric
|
||||
* @param trust How much do you trust the local network under this interface?
|
||||
* @param reliable If nonzero, this interface doesn't link to anything behind a NAT or stateful firewall
|
||||
* @return Boolean: non-zero if address was accepted and added
|
||||
*/
|
||||
int ZT1_Node_addLocalInterfaceAddress(ZT1_Node *node,const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable);
|
||||
int ZT1_Node_addLocalInterfaceAddress(ZT1_Node *node,const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust);
|
||||
|
||||
/**
|
||||
* Clear local interface addresses
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
@ -305,6 +305,21 @@ public:
|
||||
*/
|
||||
bool verify(const Identity &id) const;
|
||||
|
||||
inline bool operator==(const Dictionary &d) const
|
||||
{
|
||||
// std::map::operator== is broken on uclibc++
|
||||
if (size() != d.size())
|
||||
return false;
|
||||
const_iterator a(begin());
|
||||
const_iterator b(d.begin());
|
||||
while (a != end()) {
|
||||
if (*(a++) != *(b++))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
inline bool operator!=(const Dictionary &d) const { return (!(*this == d)); }
|
||||
|
||||
private:
|
||||
void _mkSigBuf(std::string &buf) const;
|
||||
static void _appendEsc(const char *data,unsigned int len,std::string &to);
|
||||
|
@ -185,18 +185,17 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR)
|
||||
|
||||
try {
|
||||
const unsigned int protoVersion = (*this)[ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION];
|
||||
if (protoVersion < ZT_PROTO_VERSION_MIN) {
|
||||
TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_remoteAddress.toString().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION];
|
||||
const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION];
|
||||
const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO_IDX_REVISION);
|
||||
const uint64_t timestamp = at<uint64_t>(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP);
|
||||
|
||||
Identity id;
|
||||
unsigned int destAddrPtr = id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY) + ZT_PROTO_VERB_HELLO_IDX_IDENTITY;
|
||||
|
||||
if (protoVersion < ZT_PROTO_VERSION_MIN) {
|
||||
TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_remoteAddress.toString().c_str());
|
||||
return true;
|
||||
}
|
||||
if (source() != id.address()) {
|
||||
TRACE("dropped HELLO from %s(%s): identity not for sending address",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||
return true;
|
||||
@ -906,26 +905,29 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
|
||||
unsigned int count = at<uint16_t>(ZT_PACKET_IDX_PAYLOAD);
|
||||
unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 2;
|
||||
|
||||
while (count) { // if ptr overflows Buffer will throw
|
||||
while (count--) { // if ptr overflows Buffer will throw
|
||||
// TODO: properly handle blacklisting, support other features... see Packet.hpp.
|
||||
|
||||
unsigned int flags = (*this)[ptr++];
|
||||
/*int metric = (*this)[ptr++];*/ ++ptr;
|
||||
unsigned int extLen = at<uint16_t>(ptr); ptr += 2;
|
||||
ptr += extLen; // unused right now
|
||||
unsigned int addrType = (*this)[ptr++];
|
||||
|
||||
unsigned int addrLen = (*this)[ptr++];
|
||||
|
||||
switch(addrType) {
|
||||
case 4: {
|
||||
InetAddress a(field(ptr,4),4,at<uint16_t>(ptr + 4));
|
||||
if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) )
|
||||
if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) ) {
|
||||
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
|
||||
peer->attemptToContactAt(RR,a,RR->node->now());
|
||||
}
|
||||
} break;
|
||||
case 6: {
|
||||
InetAddress a(field(ptr,16),16,at<uint16_t>(ptr + 16));
|
||||
if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) )
|
||||
if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) ) {
|
||||
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
|
||||
peer->attemptToContactAt(RR,a,RR->node->now());
|
||||
}
|
||||
} break;
|
||||
}
|
||||
ptr += addrLen;
|
||||
|
@ -63,17 +63,20 @@ struct InetAddress : public sockaddr_storage
|
||||
|
||||
/**
|
||||
* IP address scope
|
||||
*
|
||||
* Note that these values are in ascending order of path preference and
|
||||
* MUST remain that way or Path must be changed to reflect.
|
||||
*/
|
||||
enum IpScope
|
||||
{
|
||||
IP_SCOPE_NONE = 0, // not an IP address -- also the number of classes, must be last entry
|
||||
IP_SCOPE_LINK_LOCAL = 1, // 169.254.x.x, IPv6 LL
|
||||
IP_SCOPE_PRIVATE = 2, // 10.x.x.x, etc.
|
||||
IP_SCOPE_PSEUDOPRIVATE = 3, // 28.x.x.x, etc. -- unofficially unrouted IP blocks often "bogarted"
|
||||
IP_SCOPE_SHARED = 4, // 100.64.0.0/10, shared space for e.g. carrier-grade NAT
|
||||
IP_SCOPE_GLOBAL = 5, // globally routable IP address (all others)
|
||||
IP_SCOPE_LOOPBACK = 6, // 127.0.0.1
|
||||
IP_SCOPE_MULTICAST = 7 // 224.0.0.0 and other multicast IPs
|
||||
IP_SCOPE_NONE = 0, // NULL or not an IP address
|
||||
IP_SCOPE_MULTICAST = 1, // 224.0.0.0 and other V4/V6 multicast IPs
|
||||
IP_SCOPE_LOOPBACK = 2, // 127.0.0.1, ::1, etc.
|
||||
IP_SCOPE_PSEUDOPRIVATE = 3, // 28.x.x.x, etc. -- unofficially unrouted IPv4 blocks often "bogarted"
|
||||
IP_SCOPE_GLOBAL = 4, // globally routable IP address (all others)
|
||||
IP_SCOPE_LINK_LOCAL = 5, // 169.254.x.x, IPv6 LL
|
||||
IP_SCOPE_SHARED = 6, // 100.64.0.0/10, shared space for e.g. carrier-grade NAT
|
||||
IP_SCOPE_PRIVATE = 7 // 10.x.x.x, 192.168.x.x, etc.
|
||||
};
|
||||
|
||||
InetAddress() throw() { memset(this,0,sizeof(InetAddress)); }
|
||||
|
@ -432,11 +432,11 @@ void Node::freeQueryResult(void *qr)
|
||||
::free(qr);
|
||||
}
|
||||
|
||||
int Node::addLocalInterfaceAddress(const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable)
|
||||
int Node::addLocalInterfaceAddress(const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust)
|
||||
{
|
||||
if (Path::isAddressValidForPath(*(reinterpret_cast<const InetAddress *>(addr)))) {
|
||||
Mutex::Lock _l(_directPaths_m);
|
||||
_directPaths.push_back(Path(*(reinterpret_cast<const InetAddress *>(addr)),metric,(Path::Trust)trust,reliable != 0));
|
||||
_directPaths.push_back(Path(*(reinterpret_cast<const InetAddress *>(addr)),metric,(Path::Trust)trust));
|
||||
std::sort(_directPaths.begin(),_directPaths.end());
|
||||
_directPaths.erase(std::unique(_directPaths.begin(),_directPaths.end()),_directPaths.end());
|
||||
return 1;
|
||||
@ -711,10 +711,10 @@ void ZT1_Node_setNetconfMaster(ZT1_Node *node,void *networkControllerInstance)
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
|
||||
int ZT1_Node_addLocalInterfaceAddress(ZT1_Node *node,const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable)
|
||||
int ZT1_Node_addLocalInterfaceAddress(ZT1_Node *node,const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->addLocalInterfaceAddress(addr,metric,trust,reliable);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->addLocalInterfaceAddress(addr,metric,trust);
|
||||
} catch ( ... ) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
ZT1_VirtualNetworkConfig *networkConfig(uint64_t nwid) const;
|
||||
ZT1_VirtualNetworkList *networks() const;
|
||||
void freeQueryResult(void *qr);
|
||||
int addLocalInterfaceAddress(const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable);
|
||||
int addLocalInterfaceAddress(const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust);
|
||||
void clearLocalInterfaceAddresses();
|
||||
void setNetconfMaster(void *networkControllerInstance);
|
||||
|
||||
|
@ -70,7 +70,7 @@
|
||||
|
||||
/**
|
||||
* Maximum hop count allowed by packet structure (3 bits, 0-7)
|
||||
*
|
||||
*
|
||||
* This is a protocol constant. It's the maximum allowed by the length
|
||||
* of the hop counter -- three bits. See node/Constants.hpp for the
|
||||
* pragmatic forwarding limit, which is typically lower.
|
||||
@ -352,7 +352,7 @@ namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* ZeroTier packet
|
||||
*
|
||||
*
|
||||
* Packet format:
|
||||
* <[8] random initialization vector (doubles as 64-bit packet ID)>
|
||||
* <[5] destination ZT address>
|
||||
@ -362,7 +362,7 @@ namespace ZeroTier {
|
||||
* [... -- begin encryption envelope -- ...]
|
||||
* <[1] encrypted flags (top 3 bits) and verb (last 5 bits)>
|
||||
* [... verb-specific payload ...]
|
||||
*
|
||||
*
|
||||
* Packets smaller than 28 bytes are invalid and silently discarded.
|
||||
*
|
||||
* The flags/cipher/hops bit field is: FFCCCHHH where C is a 3-bit cipher
|
||||
@ -384,15 +384,15 @@ class Packet : public Buffer<ZT_PROTO_MAX_PACKET_LENGTH>
|
||||
public:
|
||||
/**
|
||||
* A packet fragment
|
||||
*
|
||||
*
|
||||
* Fragments are sent if a packet is larger than UDP MTU. The first fragment
|
||||
* is sent with its normal header with the fragmented flag set. Remaining
|
||||
* fragments are sent this way.
|
||||
*
|
||||
*
|
||||
* The fragmented bit indicates that there is at least one fragment. Fragments
|
||||
* themselves contain the total, so the receiver must "learn" this from the
|
||||
* first fragment it receives.
|
||||
*
|
||||
*
|
||||
* Fragments are sent with the following format:
|
||||
* <[8] packet ID of packet whose fragment this belongs to>
|
||||
* <[5] destination ZT address>
|
||||
@ -430,7 +430,7 @@ public:
|
||||
|
||||
/**
|
||||
* Initialize from a packet
|
||||
*
|
||||
*
|
||||
* @param p Original assembled packet
|
||||
* @param fragStart Start of fragment (raw index in packet data)
|
||||
* @param fragLen Length of fragment in bytes
|
||||
@ -446,7 +446,7 @@ public:
|
||||
|
||||
/**
|
||||
* Initialize from a packet
|
||||
*
|
||||
*
|
||||
* @param p Original assembled packet
|
||||
* @param fragStart Start of fragment (raw index in packet data)
|
||||
* @param fragLen Length of fragment in bytes
|
||||
@ -473,7 +473,7 @@ public:
|
||||
|
||||
/**
|
||||
* Get this fragment's destination
|
||||
*
|
||||
*
|
||||
* @return Destination ZT address
|
||||
*/
|
||||
inline Address destination() const { return Address(field(ZT_PACKET_FRAGMENT_IDX_DEST,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
|
||||
@ -872,7 +872,6 @@ public:
|
||||
*
|
||||
* Path record format:
|
||||
* <[1] flags>
|
||||
* <[1] metric from 0 (highest priority) to 255 (lowest priority)>
|
||||
* <[2] length of extended path characteristics or 0 for none>
|
||||
* <[...] extended path characteristics>
|
||||
* <[1] address type>
|
||||
@ -882,9 +881,8 @@ public:
|
||||
* Path record flags:
|
||||
* 0x01 - Forget this path if it is currently known
|
||||
* 0x02 - Blacklist this path, do not use
|
||||
* 0x04 - Reliable path (no NAT keepalives, etc. are necessary)
|
||||
* 0x08 - Disable encryption (trust: privacy)
|
||||
* 0x10 - Disable encryption and authentication (trust: ultimate)
|
||||
* 0x04 - Disable encryption (trust: privacy)
|
||||
* 0x08 - Disable encryption and authentication (trust: ultimate)
|
||||
*
|
||||
* Address types and addresses are of the same format as the destination
|
||||
* address type and address in HELLO.
|
||||
@ -901,15 +899,10 @@ public:
|
||||
* is set.
|
||||
*
|
||||
* Only a subset of this functionality is currently implemented: basic
|
||||
* path pushing and learning. Metrics, most flags, and OK responses are
|
||||
* not yet implemented as of 1.0.4.
|
||||
* path pushing and learning. Blacklisting and trust are not fully
|
||||
* implemented yet (encryption is still always used).
|
||||
*
|
||||
* OK response payload:
|
||||
* <[2] 16-bit number of active direct paths we already have>
|
||||
* <[2] 16-bit number of paths in push that we don't already have>
|
||||
* <[2] 16-bit number of new paths we are trying (or will try)>
|
||||
*
|
||||
* ERROR is presently not sent.
|
||||
* OK and ERROR are not generated.
|
||||
*/
|
||||
VERB_PUSH_DIRECT_PATHS = 16
|
||||
};
|
||||
@ -974,7 +967,7 @@ public:
|
||||
|
||||
/**
|
||||
* Construct a new empty packet with a unique random packet ID
|
||||
*
|
||||
*
|
||||
* Flags and hops will be zero. Other fields and data region are undefined.
|
||||
* Use the header access methods (setDestination() and friends) to fill out
|
||||
* the header. Payload should be appended; initial size is header size.
|
||||
@ -1004,7 +997,7 @@ public:
|
||||
|
||||
/**
|
||||
* Construct a new empty packet with a unique random packet ID
|
||||
*
|
||||
*
|
||||
* @param dest Destination ZT address
|
||||
* @param source Source ZT address
|
||||
* @param v Verb
|
||||
@ -1021,7 +1014,7 @@ public:
|
||||
|
||||
/**
|
||||
* Reset this packet structure for reuse in place
|
||||
*
|
||||
*
|
||||
* @param dest Destination ZT address
|
||||
* @param source Source ZT address
|
||||
* @param v Verb
|
||||
@ -1047,28 +1040,28 @@ public:
|
||||
|
||||
/**
|
||||
* Set this packet's destination
|
||||
*
|
||||
*
|
||||
* @param dest ZeroTier address of destination
|
||||
*/
|
||||
inline void setDestination(const Address &dest) { dest.copyTo(field(ZT_PACKET_IDX_DEST,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
|
||||
|
||||
/**
|
||||
* Set this packet's source
|
||||
*
|
||||
*
|
||||
* @param source ZeroTier address of source
|
||||
*/
|
||||
inline void setSource(const Address &source) { source.copyTo(field(ZT_PACKET_IDX_SOURCE,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
|
||||
|
||||
/**
|
||||
* Get this packet's destination
|
||||
*
|
||||
*
|
||||
* @return Destination ZT address
|
||||
*/
|
||||
inline Address destination() const { return Address(field(ZT_PACKET_IDX_DEST,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
|
||||
|
||||
/**
|
||||
* Get this packet's source
|
||||
*
|
||||
*
|
||||
* @return Source ZT address
|
||||
*/
|
||||
inline Address source() const { return Address(field(ZT_PACKET_IDX_SOURCE,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); }
|
||||
@ -1138,17 +1131,17 @@ public:
|
||||
|
||||
/**
|
||||
* Get this packet's unique ID (the IV field interpreted as uint64_t)
|
||||
*
|
||||
*
|
||||
* @return Packet ID
|
||||
*/
|
||||
inline uint64_t packetId() const { return at<uint64_t>(ZT_PACKET_IDX_IV); }
|
||||
|
||||
/**
|
||||
* Set packet verb
|
||||
*
|
||||
*
|
||||
* This also has the side-effect of clearing any verb flags, such as
|
||||
* compressed, and so must only be done during packet composition.
|
||||
*
|
||||
*
|
||||
* @param v New packet verb
|
||||
*/
|
||||
inline void setVerb(Verb v) { (*this)[ZT_PACKET_IDX_VERB] = (char)v; }
|
||||
@ -1186,22 +1179,22 @@ public:
|
||||
|
||||
/**
|
||||
* Attempt to compress payload if not already (must be unencrypted)
|
||||
*
|
||||
*
|
||||
* This requires that the payload at least contain the verb byte already
|
||||
* set. The compressed flag in the verb is set if compression successfully
|
||||
* results in a size reduction. If no size reduction occurs, compression
|
||||
* is not done and the flag is left cleared.
|
||||
*
|
||||
*
|
||||
* @return True if compression occurred
|
||||
*/
|
||||
bool compress();
|
||||
|
||||
/**
|
||||
* Attempt to decompress payload if it is compressed (must be unencrypted)
|
||||
*
|
||||
*
|
||||
* If payload is compressed, it is decompressed and the compressed verb
|
||||
* flag is cleared. Otherwise nothing is done and true is returned.
|
||||
*
|
||||
*
|
||||
* @return True if data is now decompressed and valid, false on error
|
||||
*/
|
||||
bool uncompress();
|
||||
|
@ -34,10 +34,31 @@
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* Base class for paths
|
||||
*
|
||||
* The base Path class is an immutable value.
|
||||
*/
|
||||
class Path
|
||||
{
|
||||
public:
|
||||
// Must be the same values as ZT1_LocalInterfaceAddressTrust in ZeroTierOne.h
|
||||
/**
|
||||
* Path trust category
|
||||
*
|
||||
* Note that this is NOT peer trust and has nothing to do with root server
|
||||
* designations or other trust metrics. This indicates how much we trust
|
||||
* this path to be secure and/or private. A trust level of normal means
|
||||
* encrypt and authenticate all traffic. Privacy trust means we can send
|
||||
* traffic in the clear. Ultimate trust means we don't even need
|
||||
* authentication. Generally a private path would be a hard-wired local
|
||||
* LAN, while an ultimate trust path would be a physically isolated private
|
||||
* server backplane.
|
||||
*
|
||||
* Nearly all paths will be normal trust. The other levels are for high
|
||||
* performance local SDN use only.
|
||||
*
|
||||
* These values MUST match ZT1_LocalInterfaceAddressTrust in ZeroTierOne.h
|
||||
*/
|
||||
enum Trust
|
||||
{
|
||||
TRUST_NORMAL = 0,
|
||||
@ -47,17 +68,15 @@ public:
|
||||
|
||||
Path() :
|
||||
_addr(),
|
||||
_metric(0),
|
||||
_trust(TRUST_NORMAL),
|
||||
_reliable(false)
|
||||
_ipScope(InetAddress::IP_SCOPE_NONE),
|
||||
_trust(TRUST_NORMAL)
|
||||
{
|
||||
}
|
||||
|
||||
Path(const InetAddress &addr,int metric,Trust trust,bool reliable) :
|
||||
Path(const InetAddress &addr,int metric,Trust trust) :
|
||||
_addr(addr),
|
||||
_metric(metric),
|
||||
_trust(trust),
|
||||
_reliable(reliable)
|
||||
_ipScope(addr.ipScope()),
|
||||
_trust(trust)
|
||||
{
|
||||
}
|
||||
|
||||
@ -67,9 +86,14 @@ public:
|
||||
inline const InetAddress &address() const throw() { return _addr; }
|
||||
|
||||
/**
|
||||
* @return Metric (higher == worse) or negative if path is blacklisted
|
||||
* @return IP scope -- faster shortcut for address().ipScope()
|
||||
*/
|
||||
inline int metric() const throw() { return _metric; }
|
||||
inline InetAddress::IpScope ipScope() const throw() { return _ipScope; }
|
||||
|
||||
/**
|
||||
* @return Preference rank, higher == better
|
||||
*/
|
||||
inline int preferenceRank() const throw() { return (int)_ipScope; } // IP scopes are in ascending rank order in InetAddress.hpp
|
||||
|
||||
/**
|
||||
* @return Path trust level
|
||||
@ -79,7 +103,10 @@ public:
|
||||
/**
|
||||
* @return True if path is considered reliable (no NAT keepalives etc. are needed)
|
||||
*/
|
||||
inline bool reliable() const throw() { return _reliable; }
|
||||
inline bool reliable() const throw()
|
||||
{
|
||||
return ((_ipScope != InetAddress::IP_SCOPE_GLOBAL)&&(_ipScope != InetAddress::IP_SCOPE_PSEUDOPRIVATE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if address is non-NULL
|
||||
@ -127,11 +154,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
InetAddress _addr;
|
||||
int _metric; // negative == blacklisted
|
||||
InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often
|
||||
Trust _trust;
|
||||
bool _reliable;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
@ -161,6 +161,21 @@ void Peer::received(
|
||||
_lastMulticastFrame = now;
|
||||
}
|
||||
|
||||
RemotePath *Peer::getBestPath(uint64_t now)
|
||||
{
|
||||
RemotePath *bestPath = (RemotePath *)0;
|
||||
uint64_t lrMax = 0;
|
||||
int rank = 0;
|
||||
for(unsigned int p=0,np=_numPaths;p<np;++p) {
|
||||
if ( (_paths[p].active(now)) && ((_paths[p].lastReceived() >= lrMax)||(_paths[p].preferenceRank() >= rank)) ) {
|
||||
lrMax = _paths[p].lastReceived();
|
||||
rank = _paths[p].preferenceRank();
|
||||
bestPath = &(_paths[p]);
|
||||
}
|
||||
}
|
||||
return bestPath;
|
||||
}
|
||||
|
||||
void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &atAddress,uint64_t now)
|
||||
{
|
||||
Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO);
|
||||
@ -200,7 +215,7 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now)
|
||||
TRACE("PING %s(%s)",_id.address().toString().c_str(),bestPath->address().toString().c_str());
|
||||
attemptToContactAt(RR,bestPath->address(),now);
|
||||
bestPath->sent(now);
|
||||
} else if ((now - bestPath->lastSend()) >= ZT_NAT_KEEPALIVE_DELAY) {
|
||||
} else if (((now - bestPath->lastSend()) >= ZT_NAT_KEEPALIVE_DELAY)&&(!bestPath->reliable())) {
|
||||
TRACE("NAT keepalive %s(%s)",_id.address().toString().c_str(),bestPath->address().toString().c_str());
|
||||
RR->node->putPacket(bestPath->address(),"",0);
|
||||
bestPath->sent(now);
|
||||
@ -214,7 +229,17 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_
|
||||
_lastDirectPathPush = now;
|
||||
|
||||
std::vector<Path> dps(RR->node->directPaths());
|
||||
TRACE("pushing %u direct paths (local interface addresses) to %s",(unsigned int)dps.size(),_id.address().toString().c_str());
|
||||
#ifdef ZT_TRACE
|
||||
{
|
||||
std::string ps;
|
||||
for(std::vector<Path>::const_iterator p(dps.begin());p!=dps.end();++p) {
|
||||
if (ps.length() > 0)
|
||||
ps.push_back(',');
|
||||
ps.append(p->address().toString());
|
||||
}
|
||||
TRACE("pushing %u direct paths (local interface addresses) to %s: %s",(unsigned int)dps.size(),_id.address().toString().c_str(),ps.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<Path>::const_iterator p(dps.begin());
|
||||
while (p != dps.end()) {
|
||||
@ -230,32 +255,25 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_
|
||||
case AF_INET6:
|
||||
addressType = 6;
|
||||
break;
|
||||
default:
|
||||
default: // we currently only push IP addresses
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t flags = 0;
|
||||
if (p->metric() < 0)
|
||||
flags |= (0x01 | 0x02); // forget and blacklist
|
||||
else {
|
||||
if (p->reliable())
|
||||
flags |= 0x04; // no NAT keepalives and such
|
||||
switch(p->trust()) {
|
||||
default:
|
||||
break;
|
||||
case Path::TRUST_PRIVACY:
|
||||
flags |= 0x08; // no encryption
|
||||
break;
|
||||
case Path::TRUST_ULTIMATE:
|
||||
flags |= (0x08 | 0x10); // no encryption, no authentication (redundant but go ahead and set both)
|
||||
break;
|
||||
}
|
||||
switch(p->trust()) {
|
||||
default:
|
||||
break;
|
||||
case Path::TRUST_PRIVACY:
|
||||
flags |= 0x04; // no encryption
|
||||
break;
|
||||
case Path::TRUST_ULTIMATE:
|
||||
flags |= (0x04 | 0x08); // no encryption, no authentication (redundant but go ahead and set both)
|
||||
break;
|
||||
}
|
||||
|
||||
outp.append(flags);
|
||||
outp.append((uint8_t)((p->metric() >= 0) ? ((p->metric() <= 255) ? p->metric() : 255) : 0));
|
||||
outp.append((uint16_t)0);
|
||||
outp.append((uint16_t)0); // no extensions
|
||||
outp.append(addressType);
|
||||
outp.append((uint8_t)((addressType == 4) ? 6 : 18));
|
||||
outp.append(p->address().rawIpData(),((addressType == 4) ? 4 : 16));
|
||||
|
@ -102,7 +102,7 @@ public:
|
||||
*
|
||||
* This is called by the decode pipe when a packet is proven to be authentic
|
||||
* and appears to be valid.
|
||||
*
|
||||
*
|
||||
* @param RR Runtime environment
|
||||
* @param remoteAddr Internet address of sender
|
||||
* @param hops ZeroTier (not IP) hops
|
||||
@ -126,18 +126,7 @@ public:
|
||||
* @param now Current time
|
||||
* @return Best path or NULL if there are no active (or fixed) direct paths
|
||||
*/
|
||||
inline RemotePath *getBestPath(uint64_t now)
|
||||
{
|
||||
RemotePath *bestPath = (RemotePath *)0;
|
||||
uint64_t lrMax = 0;
|
||||
for(unsigned int p=0,np=_numPaths;p<np;++p) {
|
||||
if ((_paths[p].active(now))&&(_paths[p].lastReceived() >= lrMax)) {
|
||||
lrMax = _paths[p].lastReceived();
|
||||
bestPath = &(_paths[p]);
|
||||
}
|
||||
}
|
||||
return bestPath;
|
||||
}
|
||||
RemotePath *getBestPath(uint64_t now);
|
||||
|
||||
/**
|
||||
* Send via best path
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
_fixed(false) {}
|
||||
|
||||
RemotePath(const InetAddress &addr,bool fixed) :
|
||||
Path(addr,0,TRUST_NORMAL,false),
|
||||
Path(addr,0,TRUST_NORMAL),
|
||||
_lastSend(0),
|
||||
_lastReceived(0),
|
||||
_fixed(fixed) {}
|
||||
@ -123,7 +123,7 @@ public:
|
||||
*/
|
||||
inline bool send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now)
|
||||
{
|
||||
if (RR->node->putPacket(_addr,data,len)) {
|
||||
if (RR->node->putPacket(address(),data,len)) {
|
||||
sent(now);
|
||||
RR->antiRec->logOutgoingZT(data,len);
|
||||
return true;
|
||||
|
@ -65,7 +65,8 @@ static const char *etherTypeName(const unsigned int etherType)
|
||||
#endif // ZT_TRACE
|
||||
|
||||
Switch::Switch(const RuntimeEnvironment *renv) :
|
||||
RR(renv)
|
||||
RR(renv),
|
||||
_lastBeaconResponse(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -76,7 +77,25 @@ Switch::~Switch()
|
||||
void Switch::onRemotePacket(const InetAddress &fromAddr,const void *data,unsigned int len)
|
||||
{
|
||||
try {
|
||||
if (len > ZT_PROTO_MIN_FRAGMENT_LENGTH) {
|
||||
if (len == 13) {
|
||||
/* LEGACY: before VERB_PUSH_DIRECT_PATHS, peers used broadcast
|
||||
* announcements on the LAN to solve the 'same network problem.' We
|
||||
* no longer send these, but we'll listen for them for a while to
|
||||
* locate peers with versions <1.0.4. */
|
||||
Address beaconAddr(reinterpret_cast<const char *>(data) + 8,5);
|
||||
if (beaconAddr == RR->identity.address())
|
||||
return;
|
||||
SharedPtr<Peer> peer(RR->topology->getPeer(beaconAddr));
|
||||
if (peer) { // we'll only respond to beacons from known peers
|
||||
const uint64_t now = RR->node->now();
|
||||
if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses
|
||||
_lastBeaconResponse = now;
|
||||
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP);
|
||||
outp.armor(peer->key(),false);
|
||||
RR->node->putPacket(fromAddr,outp.data(),outp.size());
|
||||
}
|
||||
}
|
||||
} else if (len > ZT_PROTO_MIN_FRAGMENT_LENGTH) {
|
||||
if (((const unsigned char *)data)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] == ZT_PACKET_FRAGMENT_INDICATOR) {
|
||||
_handleRemotePacketFragment(fromAddr,data,len);
|
||||
} else if (len >= ZT_PROTO_MIN_PACKET_LENGTH) {
|
||||
|
@ -99,20 +99,20 @@ public:
|
||||
|
||||
/**
|
||||
* Send a packet to a ZeroTier address (destination in packet)
|
||||
*
|
||||
*
|
||||
* The packet must be fully composed with source and destination but not
|
||||
* yet encrypted. If the destination peer is known the packet
|
||||
* is sent immediately. Otherwise it is queued and a WHOIS is dispatched.
|
||||
*
|
||||
* The packet may be compressed. Compression isn't done here.
|
||||
*
|
||||
*
|
||||
* Needless to say, the packet's source must be this node. Otherwise it
|
||||
* won't be encrypted right. (This is not used for relaying.)
|
||||
*
|
||||
* The network ID should only be specified for frames and other actual
|
||||
* network traffic. Other traffic such as controller requests and regular
|
||||
* protocol messages should specify zero.
|
||||
*
|
||||
*
|
||||
* @param packet Packet to send
|
||||
* @param encrypt Encrypt packet payload? (always true except for HELLO)
|
||||
* @param nwid Related network ID or 0 if message is not in-network traffic
|
||||
@ -168,7 +168,7 @@ public:
|
||||
|
||||
/**
|
||||
* Perform retries and other periodic timer tasks
|
||||
*
|
||||
*
|
||||
* This can return a very long delay if there are no pending timer
|
||||
* tasks. The caller should cap this comparatively vs. other values.
|
||||
*
|
||||
@ -184,6 +184,7 @@ private:
|
||||
bool _trySend(const Packet &packet,bool encrypt,uint64_t nwid);
|
||||
|
||||
const RuntimeEnvironment *const RR;
|
||||
uint64_t _lastBeaconResponse;
|
||||
|
||||
// Outsanding WHOIS requests and how many retries they've undergone
|
||||
struct WhoisRequest
|
||||
|
@ -916,7 +916,7 @@ int main(int argc,char **argv)
|
||||
r |= testCertificate();
|
||||
r |= testPhy();
|
||||
r |= testResolver();
|
||||
r |= testHttp();
|
||||
//r |= testHttp();
|
||||
|
||||
if (r)
|
||||
std::cout << std::endl << "SOMETHING FAILED!" << std::endl;
|
||||
|
@ -592,7 +592,7 @@ public:
|
||||
if (!isZT) {
|
||||
InetAddress ip(ifa->ifa_addr);
|
||||
ip.setPort(_port);
|
||||
_node->addLocalInterfaceAddress(reinterpret_cast<const struct sockaddr_storage *>(&ip),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL,0);
|
||||
_node->addLocalInterfaceAddress(reinterpret_cast<const struct sockaddr_storage *>(&ip),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL);
|
||||
}
|
||||
}
|
||||
ifa = ifa->ifa_next;
|
||||
|
@ -172,6 +172,7 @@ To create a new network with a random last six digits safely and atomically, you
|
||||
<tr><td>multicastLimit</td><td>integer</td><td>Maximum number of multicast recipients per multicast/broadcast address</td><td>yes</td></tr>
|
||||
<tr><td>creationTime</td><td>integer</td><td>Time network was created in ms since epoch</td><td>no</td></tr>
|
||||
<tr><td>revision</td><td>integer</td><td>Network config revision number</td><td>no</td></tr>
|
||||
<tr><td>memberRevisionCounter</td><td>integer</td><td>Current value of network revision counter (incremented after every member add or revision)</td><td>no</td></tr>
|
||||
<tr><td>members</td><td>[string]</td><td>Array of ZeroTier addresses of network members</td><td>no</td></tr>
|
||||
<tr><td>relays</td><td>[object]</td><td>Array of network-specific relay nodes (see below)</td><td>yes</td></tr>
|
||||
<tr><td>ipLocalRoutes</td><td>[string]</td><td>Array of IP network/netmask entries corresponding to networks routed directly via this interface (e.g. 10.0.0.0/8 to route 10.0.0.0 via this interface)</td></tr>
|
||||
@ -200,7 +201,7 @@ IP assignment pools are only used if they are within a network specified in ipLo
|
||||
<table>
|
||||
<tr><td><b>Field</b></td><td><b>Type</b></td><td><b>Description</b></td></tr>
|
||||
<tr><td>ipRangeStart</td><td>string</td><td>Start of IP assignment range</td></tr>
|
||||
<tr><td>ipRangeEnd</td><td>integer</td><td>End of IP assignment range</td></tr>
|
||||
<tr><td>ipRangeEnd</td><td>string</td><td>End of IP assignment range</td></tr>
|
||||
</table>
|
||||
|
||||
**Rule object format:**
|
||||
@ -247,4 +248,5 @@ IP related fields apply only to Ethernet frames of type IPv4 or IPV6. Otherwise
|
||||
<tr><td>activeBridge</td><td>boolean</td><td>This member is an active network bridge</td><td>yes</td></tr>
|
||||
<tr><td>identity</td><td>string</td><td>Full ZeroTier identity of member</td><td>no</td></tr>
|
||||
<tr><td>ipAssignments</td><td>[string]</td><td>Array of IP/bits IP assignments</td><td>yes</td></tr>
|
||||
<tr><td>memberRevision</td><td>integer</td><td>Member revision counter value from network at time of last revision or member creation</td><td>no</td></tr>
|
||||
</table>
|
||||
|
Loading…
Reference in New Issue
Block a user