mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-20 21:43:08 +00:00
Scratch that... more work wiring up netconf. Got to handle OK.
This commit is contained in:
parent
63fa4a684d
commit
bf5c07f79a
@ -2,17 +2,16 @@ CC=gcc
|
||||
CXX=g++
|
||||
|
||||
INCLUDES=-Iext/bin/libcrypto/include -Iext/jsoncpp/include
|
||||
LDFLAGS=-ldl
|
||||
ARCH=$(shell uname -m)
|
||||
DEFS=-DZT_ARCH="$(ARCH)" -DZT_OSNAME="linux" -DZT_TRACE
|
||||
|
||||
# Uncomment for a release optimized build
|
||||
CFLAGS=-Wall -O3 -fno-unroll-loops -fstack-protector -pthread $(INCLUDES) $(LDFLAGS) -DNDEBUG $(DEFS)
|
||||
STRIP=strip --strip-all
|
||||
#CFLAGS=-Wall -O3 -fno-unroll-loops -fstack-protector -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
#STRIP=strip --strip-all
|
||||
|
||||
# Uncomment for a debug build
|
||||
#CFLAGS=-Wall -g -pthread $(INCLUDES) $(LDFLAGS) -DZT_TRACE -DZT_LOG_STDOUT $(DEFS)
|
||||
#STRIP=echo
|
||||
CFLAGS=-Wall -g -pthread $(INCLUDES) -DZT_TRACE -DZT_LOG_STDOUT $(DEFS)
|
||||
STRIP=echo
|
||||
|
||||
CXXFLAGS=$(CFLAGS) -fno-rtti
|
||||
|
||||
@ -21,7 +20,7 @@ CXXFLAGS=$(CFLAGS) -fno-rtti
|
||||
# separate binaries for the RedHat and Debian universes to distribute via
|
||||
# auto-update. This way we get one Linux binary for all systems of a given
|
||||
# architecture.
|
||||
LIBS=ext/bin/libcrypto/linux-$(ARCH)/libcrypto.a -lm
|
||||
LIBS=ext/bin/libcrypto/linux-$(ARCH)/libcrypto.a -lm -ldl
|
||||
|
||||
include objects.mk
|
||||
|
||||
|
@ -243,6 +243,8 @@ int main(int argc,char **argv)
|
||||
sprintf(buf,"%.16llx",(unsigned long long)nwid);
|
||||
netconf["nwid"] = buf;
|
||||
netconf["isOpen"] = (isOpen ? "1" : "0");
|
||||
sprintf(buf,"%llx",(unsigned long long)Utils::now());
|
||||
netconf["ts"] = buf;
|
||||
|
||||
if (!isOpen) {
|
||||
// TODO: handle closed networks, look up private membership,
|
||||
|
@ -57,7 +57,8 @@ static const std::string _DELTA_PREFIX("~");
|
||||
bool Network::Certificate::qualifyMembership(const Network::Certificate &mc) const
|
||||
{
|
||||
// Note: optimization probably needed here, probably via some kind of
|
||||
// memoization / dynamic programming.
|
||||
// memoization / dynamic programming. But make it work first, then make
|
||||
// it fast.
|
||||
|
||||
for(const_iterator myField(begin());myField!=end();++myField) {
|
||||
if (!((myField->first.length() > 1)&&(myField->first[0] == '~'))) { // ~fields are max delta range specs
|
||||
@ -104,8 +105,8 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id)
|
||||
throw(std::runtime_error) :
|
||||
_r(renv),
|
||||
_tap(renv,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,this),
|
||||
_lastConfigUpdate(0),
|
||||
_id(id)
|
||||
_id(id),
|
||||
_lastConfigUpdate(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -143,20 +144,23 @@ bool Network::isAllowed(const Address &peer) const
|
||||
return _myCertificate.qualifyMembership(pc->second);
|
||||
} catch (std::exception &exc) {
|
||||
TRACE("isAllowed() check failed for peer %s: unexpected exception: %s",peer.toString().c_str(),exc.what());
|
||||
return false;
|
||||
} catch ( ... ) {
|
||||
TRACE("isAllowed() check failed for peer %s: unexpected exception: unknown exception",peer.toString().c_str());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Network::clean()
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
for(std::map<Address,Certificate>::iterator i=(_membershipCertificates.begin());i!=_membershipCertificates.end();) {
|
||||
if (_myCertificate.qualifyMembership(i->second))
|
||||
++i;
|
||||
else _membershipCertificates.erase(i++);
|
||||
if (_configuration.isOpen())
|
||||
_membershipCertificates.clear();
|
||||
else {
|
||||
for(std::map<Address,Certificate>::iterator i=(_membershipCertificates.begin());i!=_membershipCertificates.end();) {
|
||||
if (_myCertificate.qualifyMembership(i->second))
|
||||
++i;
|
||||
else _membershipCertificates.erase(i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ class Network : NonCopyable
|
||||
|
||||
public:
|
||||
/**
|
||||
* A certificate of network membership
|
||||
* A certificate of network membership for private network participation
|
||||
*/
|
||||
class Certificate : private Dictionary
|
||||
{
|
||||
@ -237,7 +237,10 @@ public:
|
||||
*/
|
||||
inline Certificate certificateOfMembership() const
|
||||
{
|
||||
return Certificate(get("com",""));
|
||||
const_iterator cm(find("com"));
|
||||
if (cm == end())
|
||||
return Certificate();
|
||||
else return Certificate(cm->second);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,6 +325,16 @@ public:
|
||||
*/
|
||||
inline Address controller() throw() { return Address(_id >> 24); }
|
||||
|
||||
/**
|
||||
* @return Network ID in hexadecimal form
|
||||
*/
|
||||
inline std::string toString()
|
||||
{
|
||||
char buf[64];
|
||||
sprintf(buf,"%.16llx",(unsigned long long)_id);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if network is open (no membership required)
|
||||
*/
|
||||
@ -407,12 +420,16 @@ private:
|
||||
const RuntimeEnvironment *_r;
|
||||
|
||||
EthernetTap _tap;
|
||||
|
||||
std::set<MulticastGroup> _multicastGroups;
|
||||
std::map<Address,Certificate> _membershipCertificates;
|
||||
|
||||
Config _configuration;
|
||||
Certificate _myCertificate;
|
||||
uint64_t _lastConfigUpdate;
|
||||
|
||||
uint64_t _id;
|
||||
volatile uint64_t _lastConfigUpdate;
|
||||
|
||||
Mutex _lock;
|
||||
|
||||
AtomicCounter __refCount;
|
||||
|
@ -229,6 +229,7 @@ static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictiona
|
||||
outp.append(network->id());
|
||||
outp.append((uint16_t)netconf.length());
|
||||
outp.append(netconf.data(),netconf.length());
|
||||
outp.compress();
|
||||
_r->sw->send(outp,true);
|
||||
}
|
||||
}
|
||||
@ -408,7 +409,6 @@ Node::ReasonForTermination Node::run()
|
||||
uint64_t lastPingCheck = 0;
|
||||
uint64_t lastClean = Utils::now(); // don't need to do this immediately
|
||||
uint64_t lastNetworkFingerprintCheck = 0;
|
||||
uint64_t lastAutoconfigureCheck = 0;
|
||||
uint64_t networkConfigurationFingerprint = _r->sysEnv->getNetworkConfigurationFingerprint();
|
||||
uint64_t lastMulticastCheck = 0;
|
||||
uint64_t lastMulticastAnnounceAll = 0;
|
||||
@ -418,39 +418,34 @@ Node::ReasonForTermination Node::run()
|
||||
|
||||
while (!impl->terminateNow) {
|
||||
uint64_t now = Utils::now();
|
||||
bool pingAll = false; // set to true to force a ping of *all* known direct links
|
||||
bool resynchronize = false;
|
||||
|
||||
// Detect sleep/wake by looking for delay loop pauses that are longer
|
||||
// than we intended to pause.
|
||||
if (lastDelayDelta >= ZT_SLEEP_WAKE_DETECTION_THRESHOLD) {
|
||||
lastNetworkFingerprintCheck = 0; // force network environment check
|
||||
lastMulticastCheck = 0; // force multicast group check on taps
|
||||
pingAll = true;
|
||||
|
||||
resynchronize = true;
|
||||
LOG("probable suspend/resume detected, pausing a moment for things to settle...");
|
||||
Thread::sleep(ZT_SLEEP_WAKE_SETTLE_TIME);
|
||||
}
|
||||
|
||||
// Periodically check our network environment, sending pings out to all
|
||||
// our direct links if things look like we got a different address.
|
||||
if ((now - lastNetworkFingerprintCheck) >= ZT_NETWORK_FINGERPRINT_CHECK_DELAY) {
|
||||
if ((resynchronize)||((now - lastNetworkFingerprintCheck) >= ZT_NETWORK_FINGERPRINT_CHECK_DELAY)) {
|
||||
lastNetworkFingerprintCheck = now;
|
||||
uint64_t fp = _r->sysEnv->getNetworkConfigurationFingerprint();
|
||||
if (fp != networkConfigurationFingerprint) {
|
||||
LOG("netconf fingerprint change: %.16llx != %.16llx, resyncing with network",networkConfigurationFingerprint,fp);
|
||||
networkConfigurationFingerprint = fp;
|
||||
pingAll = true;
|
||||
lastAutoconfigureCheck = 0; // check autoconf after network config change
|
||||
lastMulticastCheck = 0; // check multicast group membership after network config change
|
||||
_r->nc->whackAllTaps(); // call whack() on all tap devices
|
||||
resynchronize = true;
|
||||
_r->nc->whackAllTaps(); // call whack() on all tap devices -- hack, might go away
|
||||
}
|
||||
}
|
||||
|
||||
// Periodically check for changes in our local multicast subscriptions and broadcast
|
||||
// those changes to peers.
|
||||
if ((now - lastMulticastCheck) >= ZT_MULTICAST_LOCAL_POLL_PERIOD) {
|
||||
if ((resynchronize)||((now - lastMulticastCheck) >= ZT_MULTICAST_LOCAL_POLL_PERIOD)) {
|
||||
lastMulticastCheck = now;
|
||||
bool announceAll = ((now - lastMulticastAnnounceAll) >= ZT_MULTICAST_LIKE_ANNOUNCE_ALL_PERIOD);
|
||||
bool announceAll = ((resynchronize)||((now - lastMulticastAnnounceAll) >= ZT_MULTICAST_LIKE_ANNOUNCE_ALL_PERIOD));
|
||||
try {
|
||||
std::map< SharedPtr<Network>,std::set<MulticastGroup> > toAnnounce;
|
||||
{
|
||||
@ -478,12 +473,13 @@ Node::ReasonForTermination Node::run()
|
||||
}
|
||||
}
|
||||
|
||||
if ((now - lastPingCheck) >= ZT_PING_CHECK_DELAY) {
|
||||
if ((resynchronize)||((now - lastPingCheck) >= ZT_PING_CHECK_DELAY)) {
|
||||
lastPingCheck = now;
|
||||
try {
|
||||
if (_r->topology->amSupernode()) {
|
||||
// Supernodes do not ping anyone but each other. They also don't
|
||||
// send firewall openers, since they aren't ever firewalled.
|
||||
// Supernodes are so super they don't even have to ping out. Everyone
|
||||
// comes to them! They're also never firewalled, so they don't
|
||||
// send firewall openers.
|
||||
std::vector< SharedPtr<Peer> > sns(_r->topology->supernodePeers());
|
||||
for(std::vector< SharedPtr<Peer> >::const_iterator p(sns.begin());p!=sns.end();++p) {
|
||||
if ((now - (*p)->lastDirectSend()) > ZT_PEER_DIRECT_PING_DELAY)
|
||||
@ -492,8 +488,8 @@ Node::ReasonForTermination Node::run()
|
||||
} else {
|
||||
std::vector< SharedPtr<Peer> > needPing,needFirewallOpener;
|
||||
|
||||
if (pingAll) {
|
||||
_r->topology->eachPeer(Topology::CollectPeersWithActiveDirectPath(needPing));
|
||||
if (resynchronize) {
|
||||
_r->topology->eachPeer(Topology::CollectPeersWithDirectPath(needPing));
|
||||
} else {
|
||||
_r->topology->eachPeer(Topology::CollectPeersThatNeedPing(needPing));
|
||||
_r->topology->eachPeer(Topology::CollectPeersThatNeedFirewallOpener(needFirewallOpener));
|
||||
|
@ -127,11 +127,11 @@
|
||||
*/
|
||||
#define ZT_PROTO_MIN_FRAGMENT_LENGTH ZT_PACKET_FRAGMENT_IDX_PAYLOAD
|
||||
|
||||
// Size of bloom filter used in multicast propagation
|
||||
// Size of bloom filter used in multicast propagation graph exploration
|
||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BITS 512
|
||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES 64
|
||||
|
||||
// Field incides for parsing verbs
|
||||
// Field incides for parsing verbs -------------------------------------------
|
||||
|
||||
#define ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION (ZT_PACKET_IDX_PAYLOAD)
|
||||
#define ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION (ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION + 1)
|
||||
@ -179,11 +179,18 @@
|
||||
|
||||
#define ZT_PROTO_VERB_NETWORK_CONFIG_REFRESH_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
|
||||
|
||||
// Field indices for parsing OK and ERROR payloads of replies
|
||||
#define ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
|
||||
|
||||
#define ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
|
||||
|
||||
#define ZT_PROTO_VERB_WHOIS__ERROR__IDX_ZTADDRESS (ZT_PROTO_VERB_ERROR_IDX_PAYLOAD)
|
||||
|
||||
#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
|
||||
#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID + 8)
|
||||
#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN + 2)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
|
@ -298,6 +298,20 @@ bool PacketDecoder::_doOK(const RuntimeEnvironment *_r,const SharedPtr<Peer> &pe
|
||||
if (_r->topology->isSupernode(source()))
|
||||
_r->topology->addPeer(SharedPtr<Peer>(new Peer(_r->identity,Identity(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY))),&PacketDecoder::_CBaddPeerFromWhois,const_cast<void *>((const void *)_r));
|
||||
break;
|
||||
case Packet::VERB_NETWORK_CONFIG_REQUEST: {
|
||||
SharedPtr<Network> nw(_r->nc->network(at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID)));
|
||||
if ((nw)&&(nw->controller() == source())) {
|
||||
unsigned int dictlen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN);
|
||||
std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen);
|
||||
if (dict.length()) {
|
||||
Network::Config netconf(dict);
|
||||
if ((netconf.networkId() == nw->id())&&(netconf.peerAddress() == _r->identity.address())) { // sanity check
|
||||
LOG("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str());
|
||||
nw->setConfiguration(netconf);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
//TRACE("%s(%s): OK(%s)",source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb));
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user