|
@@ -53,6 +53,7 @@
|
|
|
#include "BandwidthAccount.hpp"
|
|
|
#include "NetworkConfig.hpp"
|
|
|
#include "CertificateOfMembership.hpp"
|
|
|
+#include "Thread.hpp"
|
|
|
|
|
|
namespace ZeroTier {
|
|
|
|
|
@@ -91,6 +92,9 @@ private:
|
|
|
* If there is no saved state, a dummy .conf is created on disk to remember
|
|
|
* this network across restarts.
|
|
|
*
|
|
|
+ * This can be a time consuming operation on some platforms (cough Windows
|
|
|
+ * cough).
|
|
|
+ *
|
|
|
* @param renv Runtime environment
|
|
|
* @param id Network ID
|
|
|
* @return Reference counted pointer to new network
|
|
@@ -109,10 +113,12 @@ public:
|
|
|
*/
|
|
|
enum Status
|
|
|
{
|
|
|
+ NETWORK_INITIALIZING,
|
|
|
NETWORK_WAITING_FOR_FIRST_AUTOCONF,
|
|
|
NETWORK_OK,
|
|
|
NETWORK_ACCESS_DENIED,
|
|
|
- NETWORK_NOT_FOUND
|
|
|
+ NETWORK_NOT_FOUND,
|
|
|
+ NETWORK_INITIALIZATION_FAILED
|
|
|
};
|
|
|
|
|
|
/**
|
|
@@ -127,11 +133,6 @@ public:
|
|
|
*/
|
|
|
inline uint64_t id() const throw() { return _id; }
|
|
|
|
|
|
- /**
|
|
|
- * @return Ethernet tap
|
|
|
- */
|
|
|
- inline EthernetTap &tap() throw() { return *_tap; }
|
|
|
-
|
|
|
/**
|
|
|
* @return Address of network's controlling node
|
|
|
*/
|
|
@@ -155,7 +156,10 @@ public:
|
|
|
inline bool updateMulticastGroups()
|
|
|
{
|
|
|
Mutex::Lock _l(_lock);
|
|
|
- return _tap->updateMulticastGroups(_multicastGroups);
|
|
|
+ EthernetTap *t = _tap;
|
|
|
+ if (t)
|
|
|
+ return _tap->updateMulticastGroups(_multicastGroups);
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -173,10 +177,34 @@ public:
|
|
|
* This is called by PacketDecoder when an update comes over the wire, or
|
|
|
* internally when an old config is reloaded from disk.
|
|
|
*
|
|
|
+ * This also cancels any netconf failure flags.
|
|
|
+ *
|
|
|
+ * The network can't accept configuration when in INITIALIZATION state,
|
|
|
+ * and so in that state this will just return false.
|
|
|
+ *
|
|
|
* @param conf Configuration in key/value dictionary form
|
|
|
* @param saveToDisk IF true (default), write config to disk
|
|
|
+ * @return True if configuration was accepted
|
|
|
+ */
|
|
|
+ bool setConfiguration(const Dictionary &conf,bool saveToDisk = true);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Set netconf failure to 'access denied'.
|
|
|
*/
|
|
|
- void setConfiguration(const Dictionary &conf,bool saveToDisk = true);
|
|
|
+ inline void setAccessDenied()
|
|
|
+ {
|
|
|
+ Mutex::Lock _l(_lock);
|
|
|
+ _netconfFailure = NETCONF_FAILURE_ACCESS_DENIED;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Set netconf failure to 'not found'.
|
|
|
+ */
|
|
|
+ inline void setNotFound()
|
|
|
+ {
|
|
|
+ Mutex::Lock _l(_lock);
|
|
|
+ _netconfFailure = NETCONF_FAILURE_NOT_FOUND;
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* Causes this network to request an updated configuration from its master node now
|
|
@@ -223,16 +251,6 @@ public:
|
|
|
*/
|
|
|
inline uint64_t lastConfigUpdate() const throw() { return _lastConfigUpdate; }
|
|
|
|
|
|
- /**
|
|
|
- * Force this network's status to a particular state based on config reply
|
|
|
- */
|
|
|
- inline void forceStatusTo(const Status s)
|
|
|
- throw()
|
|
|
- {
|
|
|
- Mutex::Lock _l(_lock);
|
|
|
- _status = s;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* @return Status of this network
|
|
|
*/
|
|
@@ -240,17 +258,20 @@ public:
|
|
|
throw()
|
|
|
{
|
|
|
Mutex::Lock _l(_lock);
|
|
|
- return _status;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * @return True if this network is in "OK" status and can accept traffic from us
|
|
|
- */
|
|
|
- inline bool isUp() const
|
|
|
- throw()
|
|
|
- {
|
|
|
- Mutex::Lock _l(_lock);
|
|
|
- return ((_config)&&(_status == NETWORK_OK)&&(_ready));
|
|
|
+ if (_tap) {
|
|
|
+ switch(_netconfFailure) {
|
|
|
+ case NETCONF_FAILURE_ACCESS_DENIED:
|
|
|
+ return NETWORK_ACCESS_DENIED;
|
|
|
+ case NETCONF_FAILURE_NOT_FOUND:
|
|
|
+ return NETWORK_NOT_FOUND;
|
|
|
+ case NETCONF_FAILURE_NONE:
|
|
|
+ if (_lastConfigUpdate > 0)
|
|
|
+ return NETWORK_OK;
|
|
|
+ else return NETWORK_WAITING_FOR_FIRST_AUTOCONF;
|
|
|
+ }
|
|
|
+ } else if (_netconfFailure == NETCONF_FAILURE_INIT_FAILED)
|
|
|
+ return NETWORK_INITIALIZATION_FAILED;
|
|
|
+ else return NETWORK_INITIALIZING;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -307,6 +328,73 @@ public:
|
|
|
return _config;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Thread main method; do not call elsewhere
|
|
|
+ */
|
|
|
+ void threadMain()
|
|
|
+ throw();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Inject a frame into tap (if it's created)
|
|
|
+ *
|
|
|
+ * @param from Origin MAC
|
|
|
+ * @param to Destination MC
|
|
|
+ * @param etherType Ethernet frame type
|
|
|
+ * @param data Frame data
|
|
|
+ * @param len Frame length
|
|
|
+ */
|
|
|
+ inline void tapPut(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
|
|
+ {
|
|
|
+ EthernetTap *t = _tap;
|
|
|
+ if (t)
|
|
|
+ t->put(from,to,etherType,data,len);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Inject a frame into tap with local MAC as destination MAC (if it's created)
|
|
|
+ *
|
|
|
+ * @param from Origin MAC
|
|
|
+ * @param etherType Ethernet frame type
|
|
|
+ * @param data Frame data
|
|
|
+ * @param len Frame length
|
|
|
+ */
|
|
|
+ inline void tapPut(const MAC &from,unsigned int etherType,const void *data,unsigned int len)
|
|
|
+ {
|
|
|
+ EthernetTap *t = _tap;
|
|
|
+ if (t)
|
|
|
+ t->put(from,t->mac(),etherType,data,len);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return Tap device name or empty string if still initializing
|
|
|
+ */
|
|
|
+ inline std::string tapDeviceName() const
|
|
|
+ {
|
|
|
+ EthernetTap *t = _tap;
|
|
|
+ if (t)
|
|
|
+ return t->deviceName();
|
|
|
+ else return std::string();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return Ethernet MAC address for this network's local interface
|
|
|
+ */
|
|
|
+ inline const MAC &mac() const
|
|
|
+ {
|
|
|
+ return _mac;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return Set of currently assigned IP addresses
|
|
|
+ */
|
|
|
+ inline std::set<InetAddress> ips() const
|
|
|
+ {
|
|
|
+ EthernetTap *t = _tap;
|
|
|
+ if (t)
|
|
|
+ return t->ips();
|
|
|
+ return std::set<InetAddress>();
|
|
|
+ }
|
|
|
+
|
|
|
private:
|
|
|
static void _CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data);
|
|
|
|
|
@@ -315,22 +403,23 @@ private:
|
|
|
void _dumpMulticastCerts();
|
|
|
|
|
|
uint64_t _id;
|
|
|
-
|
|
|
+ MAC _mac;
|
|
|
const RuntimeEnvironment *_r;
|
|
|
-
|
|
|
- EthernetTap *_tap;
|
|
|
+ EthernetTap *volatile _tap;
|
|
|
std::set<MulticastGroup> _multicastGroups;
|
|
|
-
|
|
|
std::map< std::pair<Address,MulticastGroup>,BandwidthAccount > _multicastRateAccounts;
|
|
|
std::map<Address,CertificateOfMembership> _membershipCertificates;
|
|
|
std::map<Address,uint64_t> _lastPushedMembershipCertificate;
|
|
|
SharedPtr<NetworkConfig> _config;
|
|
|
-
|
|
|
volatile uint64_t _lastConfigUpdate;
|
|
|
- volatile Status _status;
|
|
|
volatile bool _destroyOnDelete;
|
|
|
- volatile bool _ready;
|
|
|
-
|
|
|
+ volatile enum {
|
|
|
+ NETCONF_FAILURE_NONE,
|
|
|
+ NETCONF_FAILURE_ACCESS_DENIED,
|
|
|
+ NETCONF_FAILURE_NOT_FOUND,
|
|
|
+ NETCONF_FAILURE_INIT_FAILED
|
|
|
+ } _netconfFailure;
|
|
|
+ Thread _setupThread;
|
|
|
Mutex _lock;
|
|
|
|
|
|
AtomicCounter __refCount;
|