diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-01-08 14:27:55 -0800 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-01-08 14:27:55 -0800 |
commit | 64ba596e0b8d5ee4f3c7630a6315f884f09e1cab (patch) | |
tree | ba09819878bfaa2a6e86ebdcc2a34d2de9791e04 /node | |
parent | 60fb28a90a5e7b01e58b2a93351658195651e8eb (diff) | |
download | infinitytier-64ba596e0b8d5ee4f3c7630a6315f884f09e1cab.tar.gz infinitytier-64ba596e0b8d5ee4f3c7630a6315f884f09e1cab.zip |
C++ network config master ready to test.
Diffstat (limited to 'node')
-rw-r--r-- | node/IncomingPacket.cpp | 27 | ||||
-rw-r--r-- | node/InetAddress.cpp | 2 | ||||
-rw-r--r-- | node/InetAddress.h | 0 | ||||
-rw-r--r-- | node/NetworkConfigMaster.cpp | 250 | ||||
-rw-r--r-- | node/NetworkConfigMaster.hpp | 3 | ||||
-rw-r--r-- | node/Node.cpp | 21 | ||||
-rw-r--r-- | node/Packet.hpp | 67 | ||||
-rw-r--r-- | node/RuntimeEnvironment.hpp | 3 |
8 files changed, 277 insertions, 96 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 44511c13..ded83d67 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -40,6 +40,7 @@ #include "Peer.hpp" #include "NodeConfig.hpp" #include "SoftwareUpdater.hpp" +#include "NetworkConfigMaster.hpp" namespace ZeroTier { @@ -713,6 +714,24 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons { try { uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID); + unsigned int metaDataLength = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN); + Dictionary metaData((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength),metaDataLength); + uint64_t haveTimestamp = 0; + if ((ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT + metaDataLength + 8) <= size()) + haveTimestamp = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT + metaDataLength); + + if (RR->netconfMaster) { + RR->netconfMaster->doNetworkConfigRequest(_remoteAddress,packetId(),source(),nwid,metaData,haveTimestamp); + } else { + Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR); + outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST); + outp.append(packetId()); + outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION); + outp.append(nwid); + outp.armor(peer->key(),true); + _fromSock->send(_remoteAddress,outp.data(),outp.size()); + } + peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,Utils::now()); } catch (std::exception &exc) { TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); @@ -725,6 +744,14 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons bool IncomingPacket::_doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer) { try { + unsigned int ptr = ZT_PACKET_IDX_PAYLOAD; + while ((ptr + 8) <= size()) { + uint64_t nwid = at<uint64_t>(ptr); + SharedPtr<Network> nw(RR->nc->network(nwid)); + if ((nw)&&(source() == nw->controller())) + nw->requestConfiguration(); + ptr += 8; + } peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REFRESH,0,Packet::VERB_NOP,Utils::now()); } catch (std::exception &exc) { TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 18c7f031..a27182a0 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -54,7 +54,7 @@ void InetAddress::set(const std::string &ip,unsigned int port) } else { _sa.sin.sin_family = AF_INET; _sa.sin.sin_port = Utils::hton((uint16_t)port); - if (inet_pton(AF_INET,ip.c_str(),(void *)&(_sa.sin.sin_addr.s_addr)) <= 0) + if (inet_pton(AF_INET,ip.c_str(),(void *)&(_sa.sin.sin_addr.s_addr)) <= 0) _sa.saddr.sa_family = 0; } } diff --git a/node/InetAddress.h b/node/InetAddress.h deleted file mode 100644 index e69de29b..00000000 --- a/node/InetAddress.h +++ /dev/null diff --git a/node/NetworkConfigMaster.cpp b/node/NetworkConfigMaster.cpp index 3311dc65..cbf7252c 100644 --- a/node/NetworkConfigMaster.cpp +++ b/node/NetworkConfigMaster.cpp @@ -38,6 +38,9 @@ #include <sys/time.h> #include <sys/types.h> +#include <algorithm> +#include <utility> + #include "RuntimeEnvironment.hpp" #include "Switch.hpp" #include "Packet.hpp" @@ -79,7 +82,7 @@ NetworkConfigMaster::~NetworkConfigMaster() 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]; + char memberKey[128],nwids[24],addrs[16],nwKey[128],revKey[128]; Dictionary memberRecord; std::string revision,tmps2; @@ -89,6 +92,7 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin 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); + Utils::snprintf(revKey,sizeof(revKey),"zt1:network:%s:revision",nwids); TRACE("netconf: request from %s for %s (if newer than %llu)",addrs,nwids,(unsigned long long)haveTimestamp); @@ -107,8 +111,8 @@ void NetworkConfigMaster::doNetworkConfigRequest(const InetAddress &fromAddr,uin return; } - if (!_hget(nwKey,"revision",revision)) { - LOG("netconf: Redis error retrieving %s/revision",nwKey); + if (!_get(revKey,revision)) { + LOG("netconf: Redis error retrieving %s",revKey); return; } if (!revision.length()) @@ -311,6 +315,54 @@ bool NetworkConfigMaster::_hset(const char *key,const char *hashKey,const char * return true; } +bool NetworkConfigMaster::_get(const char *key,std::string &value) +{ + if (!_rc) { + if (!_reconnect()) + return false; + } + + redisReply *reply = (redisReply *)redisCommand(_rc,"GET %s",key); + if (!reply) { + if (_reconnect()) + return _get(key,value); + return false; + } + + if ((reply->type == REDIS_REPLY_STRING)&&(reply->str)) + value = reply->str; + else value = ""; + + freeReplyObject(reply); + + return true; +} + +bool NetworkConfigMaster::_smembers(const char *key,std::vector<std::string> &sdata) +{ + if (!_rc) { + if (!_reconnect()) + return false; + } + + redisReply *reply = (redisReply *)redisCommand(_rc,"SMEMBERS %s",key); + if (!reply) { + if (_reconnect()) + return _smembers(key,sdata); + return false; + } + + sdata.clear(); + if (reply->type == REDIS_REPLY_ARRAY) { + for(long i=0;i<reply->elements;++i) { + if (reply->element[i]->str) + sdata.push_back(reply->element[i]->str); + } + } + + 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]; @@ -351,13 +403,17 @@ bool NetworkConfigMaster::_initNewMember(uint64_t nwid,const Address &member,con 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]; + char memberKey[256],nwids[24],addrs[16],tss[24],nwKey[256],revKey[128],abKey[128],ipaKey[128]; Dictionary networkRecord,memberRecord,nc; + std::string revision; + Utils::snprintf(memberKey,sizeof(memberKey),"zt1:network:%s:member:%s:~",nwids,addrs); 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); + Utils::snprintf(revKey,sizeof(revKey),"zt1:network:%s:revision",nwids); + Utils::snprintf(abKey,sizeof(revKey),"zt1:network:%s:activeBridges",nwids); + Utils::snprintf(ipaKey,sizeof(revKey),"zt1:network:%s:ipAssignments",nwids); if (!_hgetall(nwKey,networkRecord)) { LOG("netconf: Redis error retrieving %s",nwKey); @@ -373,11 +429,18 @@ bool NetworkConfigMaster::_generateNetconf(uint64_t nwid,const Address &member,c return false; } - uint64_t revision = networkRecord.getHexUInt("revision",0); + if (!_get(revKey,revision)) { + LOG("netconf: Redis error retrieving %s",revKey); + return false; + } + if (!revision.length()) + revision = "0"; + bool isPrivate = networkRecord.getBoolean("private",true); ts = Utils::now(); Utils::snprintf(tss,sizeof(tss),"%llx",ts); + // Core configuration nc[ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP] = tss; nc[ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID] = nwids; nc[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO] = addrs; @@ -387,33 +450,180 @@ bool NetworkConfigMaster::_generateNetconf(uint64_t nwid,const Address &member,c 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",""); + // Multicast options + 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; + // Active bridge configuration + { + std::string activeBridgeList; + std::vector<std::string> activeBridgeSet; + if (!_smembers(abKey,activeBridgeSet)) { + LOG("netconf: Redis error retrieving set %s",abKey); + return false; + } + std::sort(activeBridgeSet.begin(),activeBridgeSet.end()); + for(std::vector<std::string>::const_iterator i(activeBridgeSet.begin());i!=activeBridgeSet.end();++i) { + if (i->length() == 10) { + if (activeBridgeList.length() > 0) + activeBridgeList.push_back(','); + activeBridgeList.append(*i); + } + } + if (activeBridgeList.length() > 0) + nc[ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES] = activeBridgeList; + } + + // IP address assignment and auto-assign using the ZeroTier-internal mechanism (not DHCP, etc.) + { + std::string ipAssignments(memberRecord.get("ipAssignments","")); + + // Get sorted, separated lists of IPv4 and IPv6 IP address assignments already present + std::vector<InetAddress> ip4s,ip6s; + { + std::vector<std::string> ips(Utils::split(ipAssignments.c_str(),",","","")); + for(std::vector<std::string>::iterator i(ips.begin());i!=ips.end();++i) { + InetAddress a(*i); + if (a.isV4()) + ip4s.push_back(a); + else if (a.isV6()) + ip6s.push_back(a); + } + } + std::sort(ip4s.begin(),ip4s.end()); + std::unique(ip4s.begin(),ip4s.end()); + std::sort(ip6s.begin(),ip6s.end()); + std::unique(ip6s.begin(),ip6s.end()); + + // If IPv4 assignment mode is 'zt', send them to the client + if (networkRecord.get("v4AssignMode","") == "zt") { + // If we have no IPv4 addresses and we have an assignment pool, auto-assign + if (ip4s.empty()) { + InetAddress v4AssignPool(networkRecord.get("v4AssignPool","")); + uint32_t pnet = Utils::ntoh(*((const uint32_t *)v4AssignPool.rawIpData())); + unsigned int pbits = v4AssignPool.netmaskBits(); + + if ((v4AssignPool.isV4())&&(pbits > 0)&&(pbits < 32)&&(pnet != 0)) { + uint32_t pmask = 0xffffffff << (32 - pbits); // netmask over network part + uint32_t invmask = ~pmask; // netmask over "random" part + + // Begin exploring the IP space by generating an IP from the ZeroTier address + uint32_t first = (((uint32_t)(member.toInt() & 0xffffffffULL)) & invmask) | (pnet & pmask); + if ((first & 0xff) == 0) + first |= 1; + else if ((first & 0xff) == 0xff) + first &= 0xfe; + + // Start by trying this first IP + uint32_t abcd = first; + + InetAddress ip; + bool gotone = false; + unsigned long sanityCounter = 0; + do { + // Convert to IPv4 InetAddress + uint32_t abcdNetworkByteOrder = Utils::hton(abcd); + ip.set(&abcdNetworkByteOrder,4,pbits); + + // Is 'ip' already assigned to another node? + std::string assignment; + if (!_hget(ipaKey,ip.toString().c_str(),assignment)) { + LOG("netconf: Redis error checking IP allocation in %s",ipaKey); + return false; + } + if ((assignment.length() != 10)||(assignment == member.toString())) { + gotone = true; + break; // not taken! + } + + // If we made it here, the IP was taken so increment and mask and try again + ++abcd; + abcd &= invmask; + abcd |= (pnet & pmask); + if ((abcd & 0xff) == 0) + abcd |= 1; + else if ((abcd & 0xff) == 0xff) + abcd &= 0xfe; + + // Don't spend insane amounts of time here -- if we have to try this hard, the user + // needs to allocate a larger IP block. + if (++sanityCounter >= 65535) + break; + } while (abcd != first); // keep going until we loop back around to 'first' + + // If we got one, add to IP list and claim in database + if (gotone) { + ip4s.push_back(ip); + _hset(ipaKey,ip.toString().c_str(),member.toString().c_str()); + if (ipAssignments.length() > 0) + ipAssignments.push_back(','); + ipAssignments.append(ip.toString()); + _hset(memberKey,"ipAssignments",ipAssignments.c_str()); + } else { + LOG("netconf: failed to allocate IP in %s for %s in network %s, need a larger pool!",v4AssignPool.toString().c_str(),addrs,nwids); + } + } + } + + // Create comma-delimited list to send to client + std::string v4s; + for(std::vector<InetAddress>::iterator i(ip4s.begin());i!=ip4s.end();++i) { + if (v4s.length() > 0) + v4s.push_back(','); + v4s.append(i->toString()); + } + if (v4s.length()) + nc[ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC] = v4s; + } + + if (networkRecord.get("v6AssignMode","") == "zt") { + // TODO: IPv6 auto-assign ... not quite baked yet. :) - 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; + std::string v6s; + for(std::vector<InetAddress>::iterator i(ip6s.begin());i!=ip6s.end();++i) { + if (v6s.length() > 0) + v6s.push_back(','); + v6s.append(i->toString()); + } + if (v6s.length()) + nc[ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC] = v6s; + } + } + // If this is a private network, generate a signed certificate of membership if (isPrivate) { - CertificateOfMembership com(revision,2,nwid,member); - if (com.sign(RR->identity)) + CertificateOfMembership com(Utils::strToU64(revision.c_str()),1,nwid,member); + if (com.sign(RR->identity)) // basically can't fail unless our identity is invalid nc[ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP] = com.toString(); + else { + LOG("netconf: failure signing certificate (identity problem?)"); + return false; + } } + // Sign netconf dictionary itself + if (!nc.sign(RR->identity)) { + LOG("netconf: failure signing dictionary (identity problem?)"); + return false; + } + + // Convert to string-serialized form into result paramter netconf = nc.toString(); - _hset(memberKey,"netconf",netconf.c_str()); - _hset(memberKey,"netconfTimestamp",tss); - _hset(memberKey,"netconfRevision",networkRecord.get("revision","0").c_str()); + // Record new netconf in database for re-use on subsequent repeat queries + { + Dictionary upd; + upd["netconf"] = netconf; + upd["netconfTimestamp"] = tss; + upd["netconfRevision"] = revision; + if (!_hmset(memberKey,upd)) { + LOG("netconf: Redis error writing to key %s",memberKey); + return false; + } + } return true; } diff --git a/node/NetworkConfigMaster.hpp b/node/NetworkConfigMaster.hpp index 29aada27..70391882 100644 --- a/node/NetworkConfigMaster.hpp +++ b/node/NetworkConfigMaster.hpp @@ -37,6 +37,7 @@ #include <stdint.h> #include <string> #include <map> +#include <vector> #include "Address.hpp" #include "Dictionary.hpp" @@ -105,6 +106,8 @@ private: 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 _get(const char *key,std::string &value); + bool _smembers(const char *key,std::vector<std::string> &sdata); 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); diff --git a/node/Node.cpp b/node/Node.cpp index f79d6402..291af590 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -76,6 +76,7 @@ #include "AntiRecursion.hpp" #include "RoutingTable.hpp" #include "HttpClient.hpp" +#include "NetworkConfigMaster.hpp" namespace ZeroTier { @@ -89,6 +90,7 @@ struct _NodeImpl volatile bool started; volatile bool running; volatile bool resynchronize; + volatile bool disableRootTopologyUpdates; std::string overrideRootTopology; @@ -100,15 +102,16 @@ struct _NodeImpl running = false; - delete renv.updater; renv.updater = (SoftwareUpdater *)0; - delete renv.nc; renv.nc = (NodeConfig *)0; // shut down all networks, close taps, etc. - delete renv.topology; renv.topology = (Topology *)0; // now we no longer need routing info - delete renv.mc; renv.mc = (Multicaster *)0; - delete renv.antiRec; renv.antiRec = (AntiRecursion *)0; - delete renv.sw; renv.sw = (Switch *)0; // order matters less from here down - delete renv.http; renv.http = (HttpClient *)0; - delete renv.prng; renv.prng = (CMWC4096 *)0; - delete renv.log; renv.log = (Logger *)0; // but stop logging last of all + delete renv.updater; renv.updater = (SoftwareUpdater *)0; + delete renv.nc; renv.nc = (NodeConfig *)0; // shut down all networks, close taps, etc. + delete renv.topology; renv.topology = (Topology *)0; // now we no longer need routing info + delete renv.mc; renv.mc = (Multicaster *)0; + delete renv.antiRec; renv.antiRec = (AntiRecursion *)0; + delete renv.sw; renv.sw = (Switch *)0; // order matters less from here down + delete renv.netconfMaster; renv.netconfMaster = (NetworkConfigMaster *)0; + delete renv.http; renv.http = (HttpClient *)0; + delete renv.prng; renv.prng = (CMWC4096 *)0; + delete renv.log; renv.log = (Logger *)0; // but stop logging last of all return reasonForTermination; } diff --git a/node/Packet.hpp b/node/Packet.hpp index d7f7fd60..4b82c2cc 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -603,72 +603,7 @@ public: */ VERB_EXT_FRAME = 7, - /* A multicast frame [old multicast protocol, deprecated]: - * <[2] 16-bit propagation depth or 0xffff for "do not forward"> - * <[320] propagation FIFO> - * <[1024] propagation bloom filter> - * [... begin signed portion ...] - * <[1] 8-bit flags, currently unused and must be 0> - * <[8] 64-bit network ID> - * <[2] 16-bit random propagation bloom filter nonce> - * <[1] number of significant bits in propagation restrict prefix> - * <[1] propagation restriction prefix (sig bits right to left)> - * <[5] ZeroTier address of node of origin> - * <[3] 24-bit multicast ID, together with origin forms GUID> - * <[6] source MAC address> - * <[6] destination multicast group MAC address> - * <[4] destination multicast group ADI field> - * <[2] 16-bit frame ethertype> - * <[2] 16-bit length of payload> - * <[...] ethernet frame payload> - * [... end of signed portion ...] - * <[2] 16-bit length of signature> - * <[...] signature (currently Ed25519/SHA-512, 96 bytes in length)> - * [<[...] network membership certificate (optional)>] - * - * Flags: - * 0x01 - Multicast frame includes network membership certificate - * for original sender for this network. - * - * When a multicast frame is received: - * - * (1) Check the signature of the signed portion of packet, discard on fail - * (2) Check for duplicate multicast, STOP if duplicate - * (3) Check rate limits, STOP if over limit - * (4) Inject into tap if member of network and packet passes other checks - * (5) Increment propagation depth, STOP if over limit - * (6) Pop topmost element off FIFO -- this is next hop - * (7) Push suggested next hops onto FIFO until full -- set corresponding - * bits in bloom filter - * (8) Send to next hop, or to a supernode if none - * - * When choosing next hops, exclude addresses corresponding to bits already - * set in the bloom filter and addresses outside the propagation restrict - * prefix. - * - * Active bridges on a network are always added as next hops for all - * multicast and broadcast traffic, as if they "like" all groups. - * - * Algorithm for setting bits in bloom filter: - * - * (1) Place the address in the least significant 40 bits of a 64-bit int. - * (2) Add the bloom filter nonce to this value. - * (3) XOR the least significant 13 bits of this value with the next most - * significant 13 bits and so on, 4 times. - * (4) This value ANDed with 0x1fff is the bit to set in the bloom filter. - * (5) Set this bit via: byte[bit >> 3] |= (0x80 >> (bit & 7)) - * - * To check bits in bloom filter perform the same computation but mask the - * bit instead of ORing it. - * - * Propagation occurs within a restrict prefix. The restrict prefix is - * applied to the least significant 16 bits of an address. The original - * sender of the multicast sets the restrict prefix and sends 2^N copies - * of the multicast frame, one for each address prefix. - * - * ERROR may be generated if a membership certificate is needed for a - * closed network. Payload will be network ID. - */ + /* DEPRECATED -- legacy support only, will go away completely soon */ VERB_P5_MULTICAST_FRAME = 8, /* Announce interest in multicast group(s): diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp index a7b7a99b..ad241535 100644 --- a/node/RuntimeEnvironment.hpp +++ b/node/RuntimeEnvironment.hpp @@ -48,6 +48,7 @@ class AntiRecursion; class EthernetTapFactory; class RoutingTable; class HttpClient; +class NetworkConfigMaster; /** * Holds global state for an instance of ZeroTier::Node @@ -77,6 +78,7 @@ public: log((Logger *)0), prng((CMWC4096 *)0), http((HttpClient *)0), + netconfMaster((NetworkConfigMaster *)0), sw((Switch *)0), mc((Multicaster *)0), antiRec((AntiRecursion *)0), @@ -122,6 +124,7 @@ public: Logger *log; // null if logging is disabled CMWC4096 *prng; HttpClient *http; + NetworkConfigMaster *netconfMaster; Switch *sw; Multicaster *mc; AntiRecursion *antiRec; |