mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-20 03:36:40 +00:00
Whole bunch of stuff: netconf, bug fixes, tweaks to ping and firewall opener timing code.
This commit is contained in:
parent
c9c63074bb
commit
e73c4cb68b
@ -114,7 +114,7 @@ EthernetTap::EthernetTap(
|
||||
|
||||
_fd = ::open("/dev/net/tun",O_RDWR);
|
||||
if (_fd <= 0)
|
||||
throw std::runtime_error("could not open TUN/TAP device");
|
||||
throw std::runtime_error(std::string("could not open TUN/TAP device: ") + strerror(errno));
|
||||
|
||||
struct ifreq ifr;
|
||||
memset(&ifr,0,sizeof(ifr));
|
||||
|
@ -68,7 +68,7 @@ class Multicaster
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* 256-bit simple bloom filter included with multicast frame packets
|
||||
* Simple bit field bloom filter included with multicast frame packets
|
||||
*/
|
||||
typedef BloomFilter<ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BITS> MulticastBloomFilter;
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
@ -35,6 +37,7 @@
|
||||
#include "Network.hpp"
|
||||
#include "Switch.hpp"
|
||||
#include "Packet.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
@ -106,14 +109,44 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t id)
|
||||
_r(renv),
|
||||
_tap(renv,renv->identity.address().toMAC(),ZT_IF_MTU,&_CBhandleTapData,this),
|
||||
_id(id),
|
||||
_lastConfigUpdate(0)
|
||||
_lastConfigUpdate(0),
|
||||
_destroyOnDelete(false)
|
||||
{
|
||||
if (controller() == _r->identity.address())
|
||||
throw std::runtime_error("configuration error: cannot add a network for which I am the netconf master");
|
||||
|
||||
std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
|
||||
std::string confs;
|
||||
if (Utils::readFile(confPath.c_str(),confs)) {
|
||||
try {
|
||||
if (confs.length()) {
|
||||
Config conf(confs);
|
||||
if (conf.containsAllFields())
|
||||
setConfiguration(Config(conf));
|
||||
}
|
||||
} catch ( ... ) {} // ignore invalid config on disk, we will re-request
|
||||
} else {
|
||||
// If the conf file isn't present, "touch" it so we'll remember
|
||||
// the existence of this network.
|
||||
FILE *tmp = fopen(confPath.c_str(),"w");
|
||||
if (tmp)
|
||||
fclose(tmp);
|
||||
}
|
||||
|
||||
requestConfiguration();
|
||||
}
|
||||
|
||||
Network::~Network()
|
||||
{
|
||||
if (_destroyOnDelete) {
|
||||
std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
|
||||
std::string mcdbPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".mcerts");
|
||||
unlink(confPath.c_str());
|
||||
unlink(mcdbPath.c_str());
|
||||
} else {
|
||||
// Causes flush of membership certs to disk
|
||||
clean();
|
||||
}
|
||||
}
|
||||
|
||||
void Network::setConfiguration(const Network::Config &conf)
|
||||
@ -124,6 +157,11 @@ void Network::setConfiguration(const Network::Config &conf)
|
||||
_configuration = conf;
|
||||
_myCertificate = conf.certificateOfMembership();
|
||||
_lastConfigUpdate = Utils::now();
|
||||
|
||||
std::string confPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".conf");
|
||||
if (!Utils::writeFile(confPath.c_str(),conf.toString())) {
|
||||
LOG("error: unable to write network configuration file at: %s",confPath.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,9 +174,17 @@ void Network::requestConfiguration()
|
||||
TRACE("requesting netconf for network %.16llx from netconf master %s",(unsigned long long)_id,controller().toString().c_str());
|
||||
Packet outp(controller(),_r->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append((uint64_t)_id);
|
||||
outp.append((uint16_t)0); // no meta-data
|
||||
_r->sw->send(outp,true);
|
||||
}
|
||||
|
||||
void Network::addMembershipCertificate(const Address &peer,const Certificate &cert)
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
if (!_configuration.isOpen())
|
||||
_membershipCertificates[peer] = cert;
|
||||
}
|
||||
|
||||
bool Network::isAllowed(const Address &peer) const
|
||||
{
|
||||
// Exceptions can occur if we do not yet have *our* configuration.
|
||||
@ -164,10 +210,39 @@ void Network::clean()
|
||||
if (_configuration.isOpen())
|
||||
_membershipCertificates.clear();
|
||||
else {
|
||||
std::string mcdbPath(_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d" + ZT_PATH_SEPARATOR_S + toString() + ".mcerts");
|
||||
FILE *mcdb = fopen(mcdbPath.c_str(),"wb");
|
||||
bool writeError = false;
|
||||
if (!mcdb) {
|
||||
LOG("error: unable to open membership cert database at: %s",mcdbPath.c_str());
|
||||
} else {
|
||||
if ((writeError)||(fwrite("MCDB0",5,1,mcdb) != 1)) // version
|
||||
writeError = true;
|
||||
}
|
||||
|
||||
for(std::map<Address,Certificate>::iterator i=(_membershipCertificates.begin());i!=_membershipCertificates.end();) {
|
||||
if (_myCertificate.qualifyMembership(i->second))
|
||||
if (_myCertificate.qualifyMembership(i->second)) {
|
||||
if ((!writeError)&&(mcdb)) {
|
||||
char tmp[ZT_ADDRESS_LENGTH];
|
||||
i->first.copyTo(tmp,ZT_ADDRESS_LENGTH);
|
||||
if ((writeError)||(fwrite(tmp,ZT_ADDRESS_LENGTH,1,mcdb) != 1))
|
||||
writeError = true;
|
||||
std::string c(i->second.toString());
|
||||
uint32_t cl = Utils::hton((uint32_t)c.length());
|
||||
if ((writeError)||(fwrite(&cl,sizeof(cl),1,mcdb) != 1))
|
||||
writeError = true;
|
||||
if ((writeError)||(fwrite(c.data(),c.length(),1,mcdb) != 1))
|
||||
writeError = true;
|
||||
}
|
||||
++i;
|
||||
else _membershipCertificates.erase(i++);
|
||||
} else _membershipCertificates.erase(i++);
|
||||
}
|
||||
|
||||
if (mcdb)
|
||||
fclose(mcdb);
|
||||
if (writeError) {
|
||||
unlink(mcdbPath.c_str());
|
||||
LOG("error: unable to write to membership cert database at: %s",mcdbPath.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +208,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
inline bool containsAllFields() const
|
||||
{
|
||||
return (contains("nwid")&&contains("peer"));
|
||||
}
|
||||
|
||||
inline std::string toString() const
|
||||
{
|
||||
return Dictionary::toString();
|
||||
@ -241,7 +246,7 @@ public:
|
||||
*/
|
||||
inline bool isOpen() const
|
||||
{
|
||||
return (get("isOpen") == "1");
|
||||
return (get("isOpen","0") == "1");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,6 +272,14 @@ private:
|
||||
|
||||
~Network();
|
||||
|
||||
/**
|
||||
* Causes all persistent disk presence to be erased on delete
|
||||
*/
|
||||
inline void destroyOnDelete()
|
||||
{
|
||||
_destroyOnDelete = true;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @return Network ID
|
||||
@ -350,16 +363,16 @@ public:
|
||||
* @param peer Peer that owns certificate
|
||||
* @param cert Certificate itself
|
||||
*/
|
||||
inline void addMembershipCertificate(const Address &peer,const Certificate &cert)
|
||||
{
|
||||
Mutex::Lock _l(_lock);
|
||||
_membershipCertificates[peer] = cert;
|
||||
}
|
||||
void addMembershipCertificate(const Address &peer,const Certificate &cert);
|
||||
|
||||
/**
|
||||
* @param peer Peer address to check
|
||||
* @return True if peer is allowed to communicate on this network
|
||||
*/
|
||||
bool isAllowed(const Address &peer) const;
|
||||
|
||||
/**
|
||||
* Perform periodic database cleaning such as removing expired membership certificates
|
||||
* Perform cleanup and possibly save state
|
||||
*/
|
||||
void clean();
|
||||
|
||||
@ -377,16 +390,20 @@ private:
|
||||
|
||||
const RuntimeEnvironment *_r;
|
||||
|
||||
// Tap and tap multicast memberships
|
||||
EthernetTap _tap;
|
||||
|
||||
std::set<MulticastGroup> _multicastGroups;
|
||||
|
||||
// Membership certificates supplied by peers
|
||||
std::map<Address,Certificate> _membershipCertificates;
|
||||
|
||||
// Configuration from network master node
|
||||
Config _configuration;
|
||||
Certificate _myCertificate;
|
||||
|
||||
uint64_t _id;
|
||||
volatile uint64_t _lastConfigUpdate;
|
||||
volatile bool _destroyOnDelete;
|
||||
|
||||
Mutex _lock;
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "Condition.hpp"
|
||||
@ -340,6 +341,9 @@ Node::ReasonForTermination Node::run()
|
||||
unlink((_r->homePath + ZT_PATH_SEPARATOR_S + "status").c_str());
|
||||
unlink((_r->homePath + ZT_PATH_SEPARATOR_S + "thisdeviceismine").c_str());
|
||||
|
||||
// Make sure networks.d exists
|
||||
mkdir((_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str(),0700);
|
||||
|
||||
// Load or generate config authentication secret
|
||||
std::string configAuthTokenPath(_r->homePath + ZT_PATH_SEPARATOR_S + "authtoken.secret");
|
||||
std::string configAuthToken;
|
||||
@ -504,7 +508,6 @@ Node::ReasonForTermination Node::run()
|
||||
_r->topology->eachPeer(Topology::CollectPeersWithDirectPath(needPing));
|
||||
} else {
|
||||
_r->topology->eachPeer(Topology::CollectPeersThatNeedPing(needPing));
|
||||
_r->topology->eachPeer(Topology::CollectPeersThatNeedFirewallOpener(needFirewallOpener));
|
||||
}
|
||||
|
||||
for(std::vector< SharedPtr<Peer> >::iterator p(needPing.begin());p!=needPing.end();++p) {
|
||||
@ -517,6 +520,7 @@ Node::ReasonForTermination Node::run()
|
||||
}
|
||||
}
|
||||
|
||||
_r->topology->eachPeer(Topology::CollectPeersThatNeedFirewallOpener(needFirewallOpener));
|
||||
for(std::vector< SharedPtr<Peer> >::iterator p(needFirewallOpener.begin());p!=needFirewallOpener.end();++p) {
|
||||
try {
|
||||
(*p)->sendFirewallOpener(_r,now);
|
||||
@ -537,7 +541,7 @@ Node::ReasonForTermination Node::run()
|
||||
if ((now - lastClean) >= ZT_DB_CLEAN_PERIOD) {
|
||||
lastClean = now;
|
||||
_r->topology->clean();
|
||||
_r->nc->cleanAllNetworks();
|
||||
_r->nc->clean();
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -72,7 +72,7 @@ void NodeConfig::whackAllTaps()
|
||||
n->second->tap().whack();
|
||||
}
|
||||
|
||||
void NodeConfig::cleanAllNetworks()
|
||||
void NodeConfig::clean()
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
for(std::map< uint64_t,SharedPtr<Network> >::const_iterator n(_networks.begin());n!=_networks.end();++n)
|
||||
@ -145,9 +145,39 @@ std::vector<std::string> NodeConfig::execute(const char *command)
|
||||
tmp.c_str());
|
||||
}
|
||||
} else if (cmd[0] == "join") {
|
||||
_P("404 join Not implemented yet.");
|
||||
if (cmd.size() > 1) {
|
||||
uint64_t nwid = strtoull(cmd[1].c_str(),(char **)0,16);
|
||||
if (nwid > 0) {
|
||||
Mutex::Lock _l(_networks_m);
|
||||
try {
|
||||
SharedPtr<Network> nw(new Network(_r,nwid));
|
||||
_networks[nwid] = nw;
|
||||
_P("200 join %.16llx OK",(unsigned long long)nwid);
|
||||
} catch (std::exception &exc) {
|
||||
_P("500 join %.16llx ERROR: %s",(unsigned long long)nwid,exc.what());
|
||||
} catch ( ... ) {
|
||||
_P("500 join %.16llx ERROR: (unknown exception)",(unsigned long long)nwid);
|
||||
}
|
||||
} else {
|
||||
_P("400 join requires a network ID (>0) in hexadecimal format");
|
||||
}
|
||||
} else {
|
||||
_P("400 join requires a network ID (>0) in hexadecimal format");
|
||||
}
|
||||
} else if (cmd[0] == "leave") {
|
||||
_P("404 leave Not implemented yet.");
|
||||
if (cmd.size() > 1) {
|
||||
Mutex::Lock _l(_networks_m);
|
||||
uint64_t nwid = strtoull(cmd[1].c_str(),(char **)0,16);
|
||||
std::map< uint64_t,SharedPtr<Network> >::iterator nw(_networks.find(nwid));
|
||||
if (nw == _networks.end()) {
|
||||
_P("404 leave %.16llx ERROR: not a member of that network",(unsigned long long)nwid);
|
||||
} else {
|
||||
nw->second->destroyOnDelete();
|
||||
_networks.erase(nw);
|
||||
}
|
||||
} else {
|
||||
_P("400 leave requires a network ID (>0) in hexadecimal format");
|
||||
}
|
||||
} else {
|
||||
_P("404 %s No such command. Use 'help' for help.",cmd[0].c_str());
|
||||
}
|
||||
|
@ -95,9 +95,9 @@ public:
|
||||
void whackAllTaps();
|
||||
|
||||
/**
|
||||
* Call clean() on all networks
|
||||
* Perform cleanup and possibly update saved state
|
||||
*/
|
||||
void cleanAllNetworks();
|
||||
void clean();
|
||||
|
||||
/**
|
||||
* @param nwid Network ID
|
||||
|
@ -610,6 +610,7 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const
|
||||
char tmp[128];
|
||||
try {
|
||||
uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
|
||||
TRACE("NETWORK_CONFIG_REQUEST for %.16llx from %s",(unsigned long long)nwid,source().toString().c_str());
|
||||
#ifndef __WINDOWS__
|
||||
if (_r->netconfService) {
|
||||
unsigned int dictLen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
|
||||
|
@ -200,7 +200,7 @@ public:
|
||||
|
||||
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
|
||||
{
|
||||
if ((p->hasDirectPath())&&((_now - p->lastFirewallOpener()) >= ZT_FIREWALL_OPENER_DELAY))
|
||||
if ((p->hasDirectPath())&&((_now - std::max(p->lastFirewallOpener(),p->lastDirectSend())) >= ZT_FIREWALL_OPENER_DELAY))
|
||||
_v.push_back(p);
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ public:
|
||||
|
||||
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
|
||||
{
|
||||
if (((p->hasActiveDirectPath(_now))||(t.isSupernode(p->address())))&&((_now - p->lastDirectSend()) >= ZT_PEER_DIRECT_PING_DELAY))
|
||||
if ( ((t.isSupernode(p->address()))&&((_now - p->lastDirectReceive()) >= ZT_PEER_DIRECT_PING_DELAY)) || ((p->hasActiveDirectPath(_now))&&((_now - p->lastDirectSend()) >= ZT_PEER_DIRECT_PING_DELAY)) )
|
||||
_v.push_back(p);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user