summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ZeroTierOne.h70
-rw-r--r--node/Network.cpp78
-rw-r--r--node/Network.hpp21
-rw-r--r--node/NetworkConfig.cpp4
-rw-r--r--node/Node.cpp8
-rw-r--r--node/Node.hpp42
6 files changed, 155 insertions, 68 deletions
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h
index 298b8157..2d0e837a 100644
--- a/include/ZeroTierOne.h
+++ b/include/ZeroTierOne.h
@@ -79,6 +79,21 @@ extern "C" {
#define ZT1_MAX_MTU 2800
/**
+ * Maximum length of network short name
+ */
+#define ZT1_MAX_NETWORK_SHORT_NAME_LENGTH 255
+
+/**
+ * Maximum number of statically assigned IP addresses per network endpoint using ZT address management (not DHCP)
+ */
+#define ZT1_MAX_ZT_ASSIGNED_ADDRESSES 16
+
+/**
+ * Maximum number of multicast group subscriptions per network
+ */
+#define ZT1_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS 8194
+
+/**
* Feature flag: this is an official ZeroTier, Inc. binary build (built with ZT_OFFICIAL_RELEASE)
*/
#define ZT1_FEATURE_FLAG_OFFICIAL 0x00000001
@@ -272,7 +287,7 @@ enum ZT1_VirtualNetworkStatus
/**
* Initialization of network failed or other internal error
*/
- ZT1_NETWORK_STATUS_INITIALIZATION_FAILED = 4
+ ZT1_NETWORK_STATUS_PORT_ERROR = 4
};
/**
@@ -323,6 +338,11 @@ typedef struct
uint64_t mac;
/**
+ * Network name (from network configuration master)
+ */
+ char name[ZT1_MAX_NETWORK_SHORT_NAME_LENGTH + 1];
+
+ /**
* Network configuration request status
*/
enum ZT1_VirtualNetworkStatus status;
@@ -360,43 +380,43 @@ typedef struct
int broadcastEnabled;
/**
- * Network config revision as reported by netconf master
- *
- * If this is zero, it means we're still waiting for our netconf.
+ * If the network is in PORT_ERROR state, this is the error most recently returned by the port config callback
*/
- unsigned long netconfRevision;
+ int portError;
/**
- * ZeroTier-assigned addresses (in sockaddr_storage structures)
- *
- * For IP, the port number of the sockaddr_XX structure contains the number
- * of bits in the address netmask. Only the IP address and port are used.
- * Other fields like interface number can be ignored.
+ * Network config revision as reported by netconf master
*
- * This is only used for ZeroTier-managed address assignments sent by the
- * virtual network's configuration master.
+ * If this is zero, it means we're still waiting for our netconf.
*/
- const struct sockaddr_storage *assignedAddresses;
+ unsigned long netconfRevision;
/**
- * Number of assigned addresses
+ * Number of multicast group subscriptions
*/
- unsigned int assignedAddressCount;
+ unsigned int multicastSubscriptionCount;
/**
* Multicast group subscriptions
*/
- ZT1_MulticastGroup *multicastSubscriptions;
+ ZT1_MulticastGroup multicastSubscriptions[ZT1_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS];
/**
- * Number of multicast group subscriptions
+ * Number of assigned addresses
*/
- unsigned int multicastSubscriptionCount;
+ unsigned int assignedAddressCount;
/**
- * Network name (from network configuration master)
+ * ZeroTier-assigned addresses (in sockaddr_storage structures)
+ *
+ * For IP, the port number of the sockaddr_XX structure contains the number
+ * of bits in the address netmask. Only the IP address and port are used.
+ * Other fields like interface number can be ignored.
+ *
+ * This is only used for ZeroTier-managed address assignments sent by the
+ * virtual network's configuration master.
*/
- const char *networkName;
+ struct sockaddr_storage assignedAddresses[ZT1_MAX_ZT_ASSIGNED_ADDRESSES];
} ZT1_VirtualNetworkConfig;
/**
@@ -539,8 +559,12 @@ typedef void ZT1_Node;
*
* The supplied config pointer is not guaranteed to remain valid, so make
* a copy if you want one.
+ *
+ * This must return 0 on success. It can return any OS-dependent error code
+ * on failure, and this results in the network being placed into the
+ * PORT_ERROR state.
*/
-typedef void (*ZT1_VirtualNetworkConfigCallback)(ZT1_Node *,uint64_t,const ZT1_VirtualNetworkConfig *);
+typedef int (*ZT1_VirtualNetworkConfigFunction)(ZT1_Node *,uint64_t,const ZT1_VirtualNetworkConfig *);
/**
* Callback for status messages
@@ -622,7 +646,7 @@ typedef void (*ZT1_VirtualNetworkFrameFunction)(ZT1_Node *,uint64_t,uint64_t,uin
* @param now Current clock in milliseconds
* @param dataStoreGetFunction Function called to get objects from persistent storage
* @param dataStorePutFunction Function called to put objects in persistent storage
- * @param virtualNetworkConfigCallback Function to be called when virtual LANs are created, deleted, or their config parameters change
+ * @param virtualNetworkConfigFunction Function to be called when virtual LANs are created, deleted, or their config parameters change
* @param statusCallback Function to receive status updates and non-fatal error notices
* @return OK (0) or error code if a fatal error condition has occurred
*/
@@ -633,7 +657,7 @@ enum ZT1_ResultCode ZT1_Node_new(
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
- ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
+ ZT1_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT1_StatusCallback statusCallback);
/**
diff --git a/node/Network.cpp b/node/Network.cpp
index dc6b87a0..7b033181 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -49,7 +49,8 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
_enabled(true),
_lastConfigUpdate(0),
_destroyed(false),
- _netconfFailure(NETCONF_FAILURE_NONE)
+ _netconfFailure(NETCONF_FAILURE_NONE),
+ _portError(0)
{
char confn[128],mcdbn[128];
Utils::snprintf(confn,sizeof(confn),"networks.d/%.16llx.conf",_id);
@@ -96,10 +97,16 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
}
requestConfiguration();
+
+ ZT1_VirtualNetworkConfig ctmp;
+ _externalConfig(&ctmp);
+ _portError = RR->node->configureVirtualNetworkPort(_id,&ctmp);
}
Network::~Network()
{
+ RR->node->configureVirtualNetworkPort(_id,(const ZT1_VirtualNetworkConfig *)0);
+
char n[128];
if (_destroyed) {
Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
@@ -179,6 +186,11 @@ bool Network::applyConfiguration(const SharedPtr<NetworkConfig> &conf)
_config = conf;
_lastConfigUpdate = RR->node->now();
_netconfFailure = NETCONF_FAILURE_NONE;
+
+ ZT1_VirtualNetworkConfig ctmp;
+ _externalConfig(&ctmp);
+ _portError = RR->node->configureVirtualNetworkPort(_id,&ctmp);
+
return true;
} else {
LOG("ignored invalid configuration for network %.16llx (configuration contains mismatched network ID or issued-to address)",(unsigned long long)_id);
@@ -368,21 +380,6 @@ void Network::clean()
}
}
-ZT1_VirtualNetworkStatus Network::status() const
-{
- Mutex::Lock _l(_lock);
- switch(_netconfFailure) {
- case NETCONF_FAILURE_ACCESS_DENIED:
- return ZT1_NETWORK_STATUS_ACCESS_DENIED;
- case NETCONF_FAILURE_NOT_FOUND:
- return ZT1_NETWORK_STATUS_NOT_FOUND;
- case NETCONF_FAILURE_NONE:
- return ((_lastConfigUpdate > 0) ? ZT1_NETWORK_STATUS_OK : ZT1_NETWORK_STATUS_REQUESTING_CONFIGURATION);
- default:
- return ZT1_NETWORK_STATUS_INITIALIZATION_FAILED;
- }
-}
-
void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
{
Mutex::Lock _l(_lock);
@@ -421,4 +418,53 @@ void Network::destroy()
_destroyed = true;
}
+ZT1_VirtualNetworkStatus Network::_status() const
+{
+ // assumes _lock is locked
+ if (_portError)
+ return ZT1_NETWORK_STATUS_PORT_ERROR;
+ switch(_netconfFailure) {
+ case NETCONF_FAILURE_ACCESS_DENIED:
+ return ZT1_NETWORK_STATUS_ACCESS_DENIED;
+ case NETCONF_FAILURE_NOT_FOUND:
+ return ZT1_NETWORK_STATUS_NOT_FOUND;
+ case NETCONF_FAILURE_NONE:
+ return ((_lastConfigUpdate > 0) ? ZT1_NETWORK_STATUS_OK : ZT1_NETWORK_STATUS_REQUESTING_CONFIGURATION);
+ default:
+ return ZT1_NETWORK_STATUS_PORT_ERROR;
+ }
+}
+
+void Network::_externalConfig(ZT1_VirtualNetworkConfig *ec) const
+{
+ // assumes _lock is locked
+ ec->nwid = _id;
+ ec->mac = MAC(RR->identity.address(),_id);
+ if (_config)
+ Utils::scopy(ec->name,sizeof(ec->name),_config->name().c_str());
+ else ec->name[0] = (char)0;
+ ec->status = _status();
+ ec->type = (_config) ? (_config->isPrivate() ? ZT1_NETWORK_TYPE_PRIVATE : ZT1_NETWORK_TYPE_PUBLIC) : ZT1_NETWORK_TYPE_PRIVATE;
+ ec->mtu = ZT_IF_MTU;
+ ec->dhcp = 0;
+ ec->bridge = (_config) ? ((_config->allowPassiveBridging() || (std::find(_config->activeBridges().begin(),_config->activeBridges().end(),RR->identity.address()) != _config->activeBridges().end())) ? 1 : 0) : 0;
+ ec->broadcastEnabled = (_config) ? (_config->enableBroadcast() ? 1 : 0) : 0;
+ ec->portError = _portError;
+ ec->netconfRevision = (_config) ? (unsigned long)_config->revision() : 0;
+
+ ec->multicastSubscriptionCount = std::max((unsigned int)_myMulticastGroups.size(),(unsigned int)ZT1_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS);
+ for(unsigned int i=0;i<ec->multicastSubscriptionCount;++i) {
+ ec->multicastSubscriptions[i].mac = _myMulticastGroups[i].mac().toInt();
+ ec->multicastSubscriptions[i].adi = _myMulticastGroups[i].adi();
+ }
+
+ if (_config) {
+ ec->assignedAddressCount = (unsigned int)_config->staticIps().size();
+ for(unsigned long i=0;i<ZT1_MAX_ZT_ASSIGNED_ADDRESSES;++i) {
+ if (i < _config->staticIps().size())
+ memcpy(&(ec->assignedAddresses[i]),&(_config->staticIps()[i]),sizeof(struct sockaddr_storage));
+ }
+ } else ec->assignedAddressCount = 0;
+}
+
} // namespace ZeroTier
diff --git a/node/Network.hpp b/node/Network.hpp
index 5693ff49..b51164a3 100644
--- a/node/Network.hpp
+++ b/node/Network.hpp
@@ -192,7 +192,20 @@ public:
/**
* @return Status of this network
*/
- ZT1_VirtualNetworkStatus status() const;
+ inline ZT1_VirtualNetworkStatus status() const
+ {
+ Mutex::Lock _l(_lock);
+ return _status();
+ }
+
+ /**
+ * @param ec Buffer to fill with externally-visible network configuration
+ */
+ inline void externalConfig(ZT1_VirtualNetworkConfig *ec) const
+ {
+ Mutex::Lock _l(_lock);
+ _externalConfig(ec);
+ }
/**
* Update and check multicast rate balance for a multicast group
@@ -321,6 +334,9 @@ public:
void destroy();
private:
+ ZT1_VirtualNetworkStatus _status() const;
+ void _externalConfig(ZT1_VirtualNetworkConfig *ec) const; // assumes _lock is locked
+
const RuntimeEnvironment *RR;
uint64_t _id;
MAC _mac; // local MAC address
@@ -340,12 +356,13 @@ private:
volatile bool _destroyed;
- volatile enum {
+ enum {
NETCONF_FAILURE_NONE,
NETCONF_FAILURE_ACCESS_DENIED,
NETCONF_FAILURE_NOT_FOUND,
NETCONF_FAILURE_INIT_FAILED
} _netconfFailure;
+ int _portError; // return value from port config callback
Mutex _lock;
diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp
index e42b0299..ba72a415 100644
--- a/node/NetworkConfig.cpp
+++ b/node/NetworkConfig.cpp
@@ -125,6 +125,8 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
_private = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE,one).c_str()) != 0);
_enableBroadcast = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST,one).c_str()) != 0);
_name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME);
+ if (_name.length() > ZT1_MAX_NETWORK_SHORT_NAME_LENGTH)
+ throw std::invalid_argument("network short name too long (max: 255 characters)");
_description = d.get(ZT_NETWORKCONFIG_DICT_KEY_DESC,std::string());
// In dictionary IPs are split into V4 and V6 addresses, but we don't really
@@ -156,6 +158,8 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
}
_staticIps.push_back(addr);
}
+ if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES)
+ throw std::invalid_argument("too many ZT-assigned IP addresses");
std::sort(_staticIps.begin(),_staticIps.end());
std::unique(_staticIps.begin(),_staticIps.end());
diff --git a/node/Node.cpp b/node/Node.cpp
index f1d107f1..29262eda 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -54,14 +54,14 @@ Node::Node(
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
- ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
+ ZT1_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT1_StatusCallback statusCallback) :
RR(new RuntimeEnvironment(this)),
_dataStoreGetFunction(dataStoreGetFunction),
_dataStorePutFunction(dataStorePutFunction),
_wirePacketSendFunction(wirePacketSendFunction),
_virtualNetworkFrameFunction(virtualNetworkFrameFunction),
- _virtualNetworkConfigCallback(virtualNetworkConfigCallback),
+ _virtualNetworkConfigFunction(virtualNetworkConfigFunction),
_statusCallback(statusCallback),
_networks(),
_networks_m(),
@@ -217,12 +217,12 @@ enum ZT1_ResultCode ZT1_Node_new(
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
- ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
+ ZT1_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT1_StatusCallback statusCallback)
{
*node = (ZT1_Node *)0;
try {
- *node = reinterpret_cast<ZT1_Node *>(new ZeroTier::Node(now,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigCallback,statusCallback));
+ *node = reinterpret_cast<ZT1_Node *>(new ZeroTier::Node(now,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,statusCallback));
return ZT1_RESULT_OK;
} catch (std::bad_alloc &exc) {
return ZT1_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
diff --git a/node/Node.hpp b/node/Node.hpp
index fe704532..5b158228 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -61,7 +61,7 @@ public:
ZT1_DataStorePutFunction dataStorePutFunction,
ZT1_WirePacketSendFunction wirePacketSendFunction,
ZT1_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
- ZT1_VirtualNetworkConfigCallback virtualNetworkConfigCallback,
+ ZT1_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
ZT1_StatusCallback statusCallback);
~Node();
@@ -115,16 +115,12 @@ public:
*/
inline bool putPacket(const InetAddress &addr,const void *data,unsigned int len,unsigned int desperation)
{
- try {
- return (_wirePacketSendFunction(
- reinterpret_cast<ZT1_Node *>(this),
- reinterpret_cast<const struct sockaddr_storage *>(&addr),
- desperation,
- data,
- len) == 0);
- } catch ( ... ) { // callbacks should not throw
- return false;
- }
+ return (_wirePacketSendFunction(
+ reinterpret_cast<ZT1_Node *>(this),
+ reinterpret_cast<const struct sockaddr_storage *>(&addr),
+ desperation,
+ data,
+ len) == 0);
}
/**
@@ -140,17 +136,15 @@ public:
*/
inline void putFrame(uint64_t nwid,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
{
- try {
- _virtualNetworkFrameFunction(
- reinterpret_cast<ZT1_Node *>(this),
- nwid,
- source.toInt(),
- dest.toInt(),
- etherType,
- vlanId,
- data,
- len);
- } catch ( ... ) {} // callbacks should not throw
+ _virtualNetworkFrameFunction(
+ reinterpret_cast<ZT1_Node *>(this),
+ nwid,
+ source.toInt(),
+ dest.toInt(),
+ etherType,
+ vlanId,
+ data,
+ len);
}
inline SharedPtr<Network> network(uint64_t nwid)
@@ -167,6 +161,8 @@ public:
inline void postEvent(ZT1_Event ev) { _statusCallback(reinterpret_cast<ZT1_Node *>(this),ev); }
+ inline int configureVirtualNetworkPort(uint64_t nwid,const ZT1_VirtualNetworkConfig *nc) { return _virtualNetworkConfigFunction(reinterpret_cast<ZT1_Node *>(this),nwid,nc); }
+
void postNewerVersionIfNewer(unsigned int major,unsigned int minor,unsigned int rev);
private:
@@ -176,7 +172,7 @@ private:
ZT1_DataStorePutFunction _dataStorePutFunction;
ZT1_WirePacketSendFunction _wirePacketSendFunction;
ZT1_VirtualNetworkFrameFunction _virtualNetworkFrameFunction;
- ZT1_VirtualNetworkConfigCallback _virtualNetworkConfigCallback;
+ ZT1_VirtualNetworkConfigFunction _virtualNetworkConfigFunction;
ZT1_StatusCallback _statusCallback;
//Dictionary _localConfig; // persisted as local.conf