summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2015-01-06 17:16:54 -0800
committerAdam Ierymenko <adam.ierymenko@gmail.com>2015-01-06 17:16:54 -0800
commit60fb28a90a5e7b01e58b2a93351658195651e8eb (patch)
tree1ec74eb3ea942c3f0272363c50dffc3a07561bfe /node
parenta369c690910d014ca79b55d07603af45343b37f5 (diff)
downloadinfinitytier-60fb28a90a5e7b01e58b2a93351658195651e8eb.tar.gz
infinitytier-60fb28a90a5e7b01e58b2a93351658195651e8eb.zip
Cleanup, new C++ netconf code is almost ready to test!
Diffstat (limited to 'node')
-rw-r--r--node/CertificateOfMembership.hpp28
-rw-r--r--node/Constants.hpp8
-rw-r--r--node/Dictionary.hpp123
-rw-r--r--node/Network.cpp19
-rw-r--r--node/NetworkConfigMaster.cpp222
-rw-r--r--node/NetworkConfigMaster.hpp14
6 files changed, 359 insertions, 55 deletions
diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp
index f76eb8ce..7a2b385b 100644
--- a/node/CertificateOfMembership.hpp
+++ b/node/CertificateOfMembership.hpp
@@ -92,12 +92,12 @@ public:
enum ReservedId
{
/**
- * Timestamp of certificate issue in milliseconds since epoch
+ * Revision number of certificate
*
- * maxDelta here defines certificate lifetime, and certs are lazily
- * pushed to other peers on a net with a frequency of 1/2 this time.
+ * Certificates may differ in revision number by a designated max
+ * delta. Differences wider than this cause certificates not to agree.
*/
- COM_RESERVED_ID_TIMESTAMP = 0,
+ COM_RESERVED_ID_REVISION = 0,
/**
* Network ID for which certificate was issued
@@ -123,14 +123,14 @@ public:
/**
* Create from required fields common to all networks
*
- * @param timestamp Timestamp of cert
+ * @param revision Revision number of certificate
* @param timestampMaxDelta Maximum variation between timestamps on this net
* @param nwid Network ID
* @param issuedTo Certificate recipient
*/
- CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo)
+ CertificateOfMembership(uint64_t revision,uint64_t revisionMaxDelta,uint64_t nwid,const Address &issuedTo)
{
- _qualifiers.push_back(_Qualifier(COM_RESERVED_ID_TIMESTAMP,timestamp,timestampMaxDelta));
+ _qualifiers.push_back(_Qualifier(COM_RESERVED_ID_REVISION,revision,revisionMaxDelta));
_qualifiers.push_back(_Qualifier(COM_RESERVED_ID_NETWORK_ID,nwid,0));
_qualifiers.push_back(_Qualifier(COM_RESERVED_ID_ISSUED_TO,issuedTo.toInt(),0xffffffffffffffffULL));
memset(_signature.data,0,_signature.size());
@@ -182,7 +182,7 @@ public:
{
if (_qualifiers.size() < 3)
return false;
- if (_qualifiers[0].id != COM_RESERVED_ID_TIMESTAMP)
+ if (_qualifiers[0].id != COM_RESERVED_ID_REVISION)
return false;
if (_qualifiers[1].id != COM_RESERVED_ID_NETWORK_ID)
return false;
@@ -192,26 +192,26 @@ public:
}
/**
- * @return Maximum delta for mandatory timestamp field or 0 if field missing
+ * @return Maximum delta for mandatory revision field or 0 if field missing
*/
- inline uint64_t timestampMaxDelta() const
+ inline uint64_t revisionMaxDelta() const
throw()
{
for(std::vector<_Qualifier>::const_iterator q(_qualifiers.begin());q!=_qualifiers.end();++q) {
- if (q->id == COM_RESERVED_ID_TIMESTAMP)
+ if (q->id == COM_RESERVED_ID_REVISION)
return q->maxDelta;
}
return 0ULL;
}
/**
- * @return Timestamp for this cert in ms since epoch (according to netconf's clock)
+ * @return Revision number for this cert
*/
- inline uint64_t timestamp() const
+ inline uint64_t revision() const
throw()
{
for(std::vector<_Qualifier>::const_iterator q(_qualifiers.begin());q!=_qualifiers.end();++q) {
- if (q->id == COM_RESERVED_ID_TIMESTAMP)
+ if (q->id == COM_RESERVED_ID_REVISION)
return q->value;
}
return 0ULL;
diff --git a/node/Constants.hpp b/node/Constants.hpp
index 557c8208..af1322ab 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -370,14 +370,6 @@
#define ZT_ANTIRECURSION_HISTORY_SIZE 16
/**
- * TTL for certificates of membership on private networks
- *
- * This is the max delta for the timestamp field of a COM, so it's a window
- * plus or minus the certificate's timestamp. In milliseconds.
- */
-#define ZT_NETWORK_CERTIFICATE_TTL_WINDOW (ZT_NETWORK_AUTOCONF_DELAY * 4)
-
-/**
* How often to broadcast beacons over physical local LANs
*/
#define ZT_BEACON_INTERVAL 30000
diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp
index c0bc13a2..a104ea1a 100644
--- a/node/Dictionary.hpp
+++ b/node/Dictionary.hpp
@@ -35,6 +35,7 @@
#include <stdexcept>
#include "Constants.hpp"
+#include "Utils.hpp"
// Three fields are added/updated by sign()
#define ZT_DICTIONARY_SIGNATURE "~!ed25519"
@@ -108,6 +109,128 @@ public:
}
/**
+ * @param key Key to get
+ * @param dfl Default boolean result if key not found or empty (default: false)
+ * @return Boolean value of key
+ */
+ inline bool getBoolean(const std::string &key,bool dfl = false) const
+ {
+ const_iterator e(find(key));
+ if (e == end())
+ return dfl;
+ if (e->second.length() < 1)
+ return dfl;
+ switch(e->second[0]) {
+ case '1':
+ case 't':
+ case 'T':
+ case 'y':
+ case 'Y':
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param key Key to get
+ * @param dfl Default value if not present (default: 0)
+ * @return Value converted to unsigned 64-bit int or 0 if not found
+ */
+ inline uint64_t getUInt(const std::string &key,uint64_t dfl = 0) const
+ {
+ const_iterator e(find(key));
+ if (e == end())
+ return dfl;
+ return Utils::strToU64(e->second.c_str());
+ }
+
+ /**
+ * @param key Key to get
+ * @param dfl Default value if not present (default: 0)
+ * @return Value converted to unsigned 64-bit int or 0 if not found
+ */
+ inline uint64_t getHexUInt(const std::string &key,uint64_t dfl = 0) const
+ {
+ const_iterator e(find(key));
+ if (e == end())
+ return dfl;
+ return Utils::hexStrToU64(e->second.c_str());
+ }
+
+ /**
+ * @param key Key to get
+ * @param dfl Default value if not present (default: 0)
+ * @return Value converted to signed 64-bit int or 0 if not found
+ */
+ inline int64_t getInt(const std::string &key,int64_t dfl = 0) const
+ {
+ const_iterator e(find(key));
+ if (e == end())
+ return dfl;
+ return Utils::strTo64(e->second.c_str());
+ }
+
+ /**
+ * @param key Key to set
+ * @param value String value
+ */
+ inline void set(const std::string &key,const char *value)
+ {
+ (*this)[key] = value;
+ }
+
+ /**
+ * @param key Key to set
+ * @param value String value
+ */
+ inline void set(const std::string &key,const std::string &value)
+ {
+ (*this)[key] = value;
+ }
+
+ /**
+ * @param key Key to set
+ * @param value Boolean value
+ */
+ inline void set(const std::string &key,bool value)
+ {
+ (*this)[key] = ((value) ? "1" : "0");
+ }
+
+ /**
+ * @param key Key to set
+ * @param value Integer value
+ */
+ inline void set(const std::string &key,uint64_t value)
+ {
+ char tmp[24];
+ Utils::snprintf(tmp,sizeof(tmp),"%llu",(unsigned long long)value);
+ (*this)[key] = tmp;
+ }
+
+ /**
+ * @param key Key to set
+ * @param value Integer value
+ */
+ inline void set(const std::string &key,int64_t value)
+ {
+ char tmp[24];
+ Utils::snprintf(tmp,sizeof(tmp),"%lld",(long long)value);
+ (*this)[key] = tmp;
+ }
+
+ /**
+ * @param key Key to set
+ * @param value Integer value
+ */
+ inline void setHex(const std::string &key,uint64_t value)
+ {
+ char tmp[24];
+ Utils::snprintf(tmp,sizeof(tmp),"%llx",(unsigned long long)value);
+ (*this)[key] = tmp;
+ }
+
+ /**
* @param key Key to check
* @return True if dictionary contains key
*/
diff --git a/node/Network.cpp b/node/Network.cpp
index 26d8684f..df741026 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -352,7 +352,7 @@ void Network::addMembershipCertificate(const CertificateOfMembership &cert,bool
}
// If we made it past authentication, update cert
- if (cert.timestamp() >= old.timestamp())
+ if (cert.revision() != old.revision())
old = cert;
}
@@ -360,17 +360,10 @@ bool Network::peerNeedsOurMembershipCertificate(const Address &to,uint64_t now)
{
Mutex::Lock _l(_lock);
if ((_config)&&(!_config->isPublic())&&(_config->com())) {
- uint64_t pushInterval = _config->com().timestampMaxDelta() / 2;
- if (pushInterval) {
- // Give a 1s margin around +/- 1/2 max delta to account for network latency
- if (pushInterval > 1000)
- pushInterval -= 1000;
-
- uint64_t &lastPushed = _lastPushedMembershipCertificate[to];
- if ((now - lastPushed) > pushInterval) {
- lastPushed = now;
- return true;
- }
+ uint64_t &lastPushed = _lastPushedMembershipCertificate[to];
+ if ((now - lastPushed) > (ZT_NETWORK_AUTOCONF_DELAY / 2)) {
+ lastPushed = now;
+ return true;
}
}
return false;
@@ -421,7 +414,7 @@ void Network::clean()
// Clean entries from the last pushed tracking map if they're so old as
// to be no longer relevant.
- uint64_t forgetIfBefore = now - (_config->com().timestampMaxDelta() * 3ULL);
+ uint64_t forgetIfBefore = now - (ZT_PEER_ACTIVITY_TIMEOUT * 16); // arbitrary reasonable cutoff
for(std::map<Address,uint64_t>::iterator lp(_lastPushedMembershipCertificate.begin());lp!=_lastPushedMembershipCertificate.end();) {
if (lp->second < forgetIfBefore)
_lastPushedMembershipCertificate.erase(lp++);
diff --git a/node/NetworkConfigMaster.cpp b/node/NetworkConfigMaster.cpp
index 3357b150..3311dc65 100644
--- a/node/NetworkConfigMaster.cpp
+++ b/node/NetworkConfigMaster.cpp
@@ -26,6 +26,7 @@
*/
#include "Constants.hpp"
+#include "NetworkConfigMaster.hpp"
#ifdef ZT_ENABLE_NETCONF_MASTER
@@ -37,7 +38,6 @@
#include <sys/time.h>
#include <sys/types.h>
-#include "NetworkConfigMaster.hpp"
#include "RuntimeEnvironment.hpp"
#include "Switch.hpp"
#include "Packet.hpp"
@@ -45,6 +45,9 @@
#include "Utils.hpp"
#include "Node.hpp"
#include "Logger.hpp"
+#include "Topology.hpp"
+#include "Peer.hpp"
+#include "CertificateOfMembership.hpp"
// Redis timeout in seconds
#define ZT_NETCONF_REDIS_TIMEOUT 10
@@ -74,13 +77,93 @@ NetworkConfigMaster::~NetworkConfigMaster()
redisFree(_rc);
}
-void NetworkConfigMaster::doNetworkConfigRequest(
- uint64_t packetId,
- const Address &from,
- uint64_t nwid,
- const Dictionary &metaData,
- uint64_t haveTimestamp)
+void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uint64_t packetId,const Address &member,uint64_t nwid,const Dictionary &metaData,uint64_t haveTimestamp)
{
+ char memberKey[256],nwids[24],addrs[16],nwKey[256];
+ Dictionary memberRecord;
+ std::string revision,tmps2;
+
+ Mutex::Lock _l(_lock);
+
+ Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
+ Utils::snprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)member.toInt());
+ Utils::snprintf(memberKey,sizeof(memberKey),"zt1:network:%s:member:%s:~",nwids,addrs);
+ Utils::snprintf(nwKey,sizeof(nwKey),"zt1:network:%s:~",nwids);
+
+ TRACE("netconf: request from %s for %s (if newer than %llu)",addrs,nwids,(unsigned long long)haveTimestamp);
+
+ if (!_hget(nwKey,"id",tmps2)) {
+ LOG("netconf: Redis error retrieving %s/id",nwKey);
+ return;
+ }
+ if (tmps2 != nwids) {
+ TRACE("netconf: network %s not found",nwids);
+ Packet outp(member,RR->identity.address(),Packet::VERB_ERROR);
+ outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
+ outp.append(packetId);
+ outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
+ outp.append(nwid);
+ RR->sw->send(outp,true);
+ return;
+ }
+
+ if (!_hget(nwKey,"revision",revision)) {
+ LOG("netconf: Redis error retrieving %s/revision",nwKey);
+ return;
+ }
+ if (!revision.length())
+ revision = "0";
+
+ if (!_hgetall(memberKey,memberRecord)) {
+ LOG("netconf: Redis error retrieving %s",memberKey);
+ return;
+ }
+
+ if ((memberRecord.size() == 0)||(memberRecord.get("id","") != addrs)||(memberRecord.get("nwid","") != nwids)) {
+ if (!_initNewMember(nwid,member,metaData,memberRecord))
+ return;
+ }
+
+ if (memberRecord.getBoolean("authorized")) {
+ uint64_t ts = memberRecord.getHexUInt("netconfTimestamp",0);
+ std::string netconf(memberRecord.get("netconf",""));
+
+ Dictionary upd;
+ upd.setHex("netconfClientTimestamp",haveTimestamp);
+ if (fromAddr)
+ upd.set("lastAt",fromAddr.toString());
+ upd.setHex("lastSeen",Utils::now());
+ _hmset(memberKey,upd);
+
+ if (((ts == 0)||(netconf.length() == 0))||(memberRecord.get("netconfRevision","") != revision)) {
+ if (!_generateNetconf(nwid,member,metaData,netconf,ts))
+ return;
+ }
+
+ if (ts > haveTimestamp) {
+ TRACE("netconf: sending %u bytes of netconf data to %s",netconf.length(),addrs);
+ Packet outp(member,RR->identity.address(),Packet::VERB_OK);
+ outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
+ outp.append(packetId);
+ outp.append(nwid);
+ outp.append((uint16_t)netconf.length());
+ outp.append(netconf.data(),netconf.length());
+ outp.compress();
+ if (outp.size() > ZT_PROTO_MAX_PACKET_LENGTH) { // sanity check -- this would be weird
+ TRACE("netconf: compressed packet exceeds ZT_PROTO_MAX_PACKET_LENGTH!");
+ return;
+ }
+ RR->sw->send(outp,true);
+ }
+ } else {
+ TRACE("netconf: access denied for %s on %s",addrs,nwids);
+ Packet outp(member,RR->identity.address(),Packet::VERB_ERROR);
+ outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
+ outp.append(packetId);
+ outp.append((unsigned char)Packet::ERROR_NETWORK_ACCESS_DENIED_);
+ outp.append(nwid);
+ RR->sw->send(outp,true);
+ }
}
bool NetworkConfigMaster::_reconnect()
@@ -92,7 +175,7 @@ bool NetworkConfigMaster::_reconnect()
tv.tv_sec = ZT_NETCONF_REDIS_TIMEOUT;
tv.tv_usec = 0;
- _rc = redisConnectWithTimeout(_redisHost.c_str(),_redisPort,&tv);
+ _rc = redisConnectWithTimeout(_redisHost.c_str(),_redisPort,tv);
if (!_rc)
return false;
if (_rc->err) {
@@ -100,14 +183,14 @@ bool NetworkConfigMaster::_reconnect()
_rc = (redisContext *)0;
return false;
}
- redisSetTimeout(_rc,&tv); // necessary???
+ redisSetTimeout(_rc,tv); // necessary???
// TODO: support AUTH and SELECT !!!
return true;
}
-bool NetworkConfigMaster::_hgetall(const char *key,std::map<std::string,std::string> &hdata)
+bool NetworkConfigMaster::_hgetall(const char *key,Dictionary &hdata)
{
if (!_rc) {
if (!_reconnect())
@@ -125,11 +208,11 @@ bool NetworkConfigMaster::_hgetall(const char *key,std::map<std::string,std::str
if (reply->type == REDIS_REPLY_ARRAY) {
for(long i=0;i<reply->elements;) {
try {
- const char *k = reply->elements[i]->str;
+ const char *k = reply->element[i]->str;
if (++i >= reply->elements)
break;
- if ((k)&&(reply->elements[i]->str))
- hdata[k] = reply->elements[i]->str;
+ if ((k)&&(reply->element[i]->str))
+ hdata[k] = reply->element[i]->str;
++i;
} catch ( ... ) {
break; // memory safety
@@ -142,9 +225,9 @@ bool NetworkConfigMaster::_hgetall(const char *key,std::map<std::string,std::str
return true;
}
-bool NetworkConfigMaster::_hmset(const char *key,const std::map<std::string,std::string> &hdata)
+bool NetworkConfigMaster::_hmset(const char *key,const Dictionary &hdata)
{
- const const char *hargv[1024];
+ const char *hargv[1024];
if (!hdata.size())
return true;
@@ -157,7 +240,7 @@ bool NetworkConfigMaster::_hmset(const char *key,const std::map<std::string,std:
hargv[0] = "HMSET";
hargv[1] = key;
int hargc = 2;
- for(std::map<std::string,std::string>::const_iterator i(hdata.begin());i!=hdata.end();++i) {
+ for(Dictionary::const_iterator i(hdata.begin());i!=hdata.end();++i) {
if (hargc >= 1024)
break;
hargv[hargc++] = i->first.c_str();
@@ -228,6 +311,113 @@ bool NetworkConfigMaster::_hset(const char *key,const char *hashKey,const char *
return true;
}
+bool NetworkConfigMaster::_initNewMember(uint64_t nwid,const Address &member,const Dictionary &metaData,Dictionary &memberRecord)
+{
+ char memberKey[256],nwids[24],addrs[16],nwKey[256];
+ Dictionary networkRecord;
+
+ Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
+ Utils::snprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)member.toInt());
+ Utils::snprintf(memberKey,sizeof(memberKey),"zt1:network:%s:member:%s:~",nwids,addrs);
+ Utils::snprintf(nwKey,sizeof(nwKey),"zt1:network:%s:~",nwids);
+
+ if (!_hgetall(nwKey,networkRecord)) {
+ LOG("netconf: Redis error retrieving %s",nwKey);
+ return false;
+ }
+ if (networkRecord.get("id","") != nwids) {
+ TRACE("netconf: network %s not found (initNewMember)",nwids);
+ return false;
+ }
+
+ memberRecord.clear();
+ memberRecord["id"] = addrs;
+ memberRecord["nwid"] = nwids;
+ memberRecord["authorized"] = (networkRecord.getBoolean("private",true) ? "0" : "1"); // auto-authorize on public networks
+ memberRecord.setHex("firstSeen",Utils::now());
+ {
+ SharedPtr<Peer> peer(RR->topology->getPeer(member));
+ if (peer)
+ memberRecord["identity"] = peer->identity().toString(false);
+ }
+
+ if (!_hmset(memberKey,memberRecord)) {
+ LOG("netconf: Redis error storing %s for new member %s",memberKey,addrs);
+ return false;
+ }
+
+ return true;
+}
+
+bool NetworkConfigMaster::_generateNetconf(uint64_t nwid,const Address &member,const Dictionary &metaData,std::string &netconf,uint64_t &ts)
+{
+ char memberKey[256],nwids[24],addrs[16],tss[24],nwKey[256];
+ Dictionary networkRecord,memberRecord,nc;
+
+ Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
+ Utils::snprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)member.toInt());
+ Utils::snprintf(memberKey,sizeof(memberKey),"zt1:network:%s:member:%s:~",nwids,addrs);
+ Utils::snprintf(nwKey,sizeof(nwKey),"zt1:network:%s:~",nwids);
+
+ if (!_hgetall(nwKey,networkRecord)) {
+ LOG("netconf: Redis error retrieving %s",nwKey);
+ return false;
+ }
+ if (networkRecord.get("id","") != nwids) {
+ TRACE("netconf: network %s not found (generateNetconf)",nwids);
+ return false;
+ }
+
+ if (!_hgetall(memberKey,memberRecord)) {
+ LOG("netconf: Redis error retrieving %s",memberKey);
+ return false;
+ }
+
+ uint64_t revision = networkRecord.getHexUInt("revision",0);
+ bool isPrivate = networkRecord.getBoolean("private",true);
+ ts = Utils::now();
+ Utils::snprintf(tss,sizeof(tss),"%llx",ts);
+
+ nc[ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP] = tss;
+ nc[ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID] = nwids;
+ nc[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO] = addrs;
+ nc[ZT_NETWORKCONFIG_DICT_KEY_PRIVATE] = isPrivate ? "1" : "0";
+ nc[ZT_NETWORKCONFIG_DICT_KEY_NAME] = networkRecord.get("name",nwids);
+ nc[ZT_NETWORKCONFIG_DICT_KEY_DESC] = networkRecord.get("desc","");
+ nc[ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST] = networkRecord.getBoolean("enableBroadcast",true) ? "1" : "0";
+ nc[ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING] = networkRecord.getBoolean("allowPassiveBridging",false) ? "1" : "0";
+ nc[ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES] = networkRecord.get("etherTypes","");
+ nc[ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES] = networkRecord.get("multicastRates","");
+
+ uint64_t ml = networkRecord.getHexUInt("multicastLimit",0);
+ if (ml > 0)
+ nc.setHex(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,ml);
+
+ std::string activeBridgeList;
+ if (activeBridgeList.length() > 0)
+ nc[ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES] = activeBridgeList;
+
+ std::string v4s,v6s;
+ if (v4s.length())
+ nc[ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC] = v4s;
+ if (v6s.length())
+ nc[ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC] = v6s;
+
+ if (isPrivate) {
+ CertificateOfMembership com(revision,2,nwid,member);
+ if (com.sign(RR->identity))
+ nc[ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP] = com.toString();
+ }
+
+ netconf = nc.toString();
+
+ _hset(memberKey,"netconf",netconf.c_str());
+ _hset(memberKey,"netconfTimestamp",tss);
+ _hset(memberKey,"netconfRevision",networkRecord.get("revision","0").c_str());
+
+ return true;
+}
+
} // namespace ZeroTier
#endif // ZT_ENABLE_NETCONF_MASTER
diff --git a/node/NetworkConfigMaster.hpp b/node/NetworkConfigMaster.hpp
index 636b197e..29aada27 100644
--- a/node/NetworkConfigMaster.hpp
+++ b/node/NetworkConfigMaster.hpp
@@ -41,6 +41,7 @@
#include "Address.hpp"
#include "Dictionary.hpp"
#include "Mutex.hpp"
+#include "InetAddress.hpp"
#include <hiredis/hiredis.h>
@@ -82,15 +83,17 @@ public:
* This is a blocking call, so rate is limited by Redis. It will fail
* and log its failure if the Redis server is not available or times out.
*
+ * @param fromAddr Originating IP address
* @param packetId 64-bit packet ID
- * @param from Originating peer ZeroTier address
+ * @param member Originating peer ZeroTier address
* @param nwid 64-bit network ID
* @param metaData Meta-data bundled with request (empty if none)
* @param haveTimestamp Timestamp requesting peer has or 0 if none or not included
*/
void doNetworkConfigRequest(
+ const InetAddress &fromAddr,
uint64_t packetId,
- const Address &from,
+ const Address &member,
uint64_t nwid,
const Dictionary &metaData,
uint64_t haveTimestamp);
@@ -98,11 +101,14 @@ public:
private:
// These assume _lock is locked
bool _reconnect();
- bool _hgetall(const char *key,std::map<std::string,std::string> &hdata);
- bool _hmset(const char *key,const std::map<std::string,std::string> &hdata);
+ bool _hgetall(const char *key,Dictionary &hdata);
+ bool _hmset(const char *key,const Dictionary &hdata);
bool _hget(const char *key,const char *hashKey,std::string &value);
bool _hset(const char *key,const char *hashKey,const char *value);
+ bool _initNewMember(uint64_t nwid,const Address &member,const Dictionary &metaData,Dictionary &memberRecord);
+ bool _generateNetconf(uint64_t nwid,const Address &member,const Dictionary &metaData,std::string &netconf,uint64_t &ts);
+
Mutex _lock;
std::string _redisHost;