From 8001b2c0cb6d35bfbc7b7be78d1a8b6d0fafbd53 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Apr 2015 16:52:52 -0700 Subject: [PATCH] Network now calls port config function as per new API. --- include/ZeroTierOne.h | 74 +++++++++++++++++++++++++-------------- node/Network.cpp | 78 +++++++++++++++++++++++++++++++++--------- node/Network.hpp | 21 ++++++++++-- node/NetworkConfig.cpp | 4 +++ node/Node.cpp | 8 ++--- node/Node.hpp | 42 ++++++++++------------- 6 files changed, 157 insertions(+), 70 deletions(-) diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 298b8157c..2d0e837a8 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -78,6 +78,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) */ @@ -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 }; /** @@ -322,6 +337,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 */ @@ -359,6 +379,11 @@ typedef struct */ int broadcastEnabled; + /** + * If the network is in PORT_ERROR state, this is the error most recently returned by the port config callback + */ + int portError; + /** * Network config revision as reported by netconf master * @@ -366,6 +391,21 @@ typedef struct */ unsigned long netconfRevision; + /** + * Number of multicast group subscriptions + */ + unsigned int multicastSubscriptionCount; + + /** + * Multicast group subscriptions + */ + ZT1_MulticastGroup multicastSubscriptions[ZT1_MAX_NETWORK_MULTICAST_SUBSCRIPTIONS]; + + /** + * Number of assigned addresses + */ + unsigned int assignedAddressCount; + /** * ZeroTier-assigned addresses (in sockaddr_storage structures) * @@ -376,27 +416,7 @@ typedef struct * This is only used for ZeroTier-managed address assignments sent by the * virtual network's configuration master. */ - const struct sockaddr_storage *assignedAddresses; - - /** - * Number of assigned addresses - */ - unsigned int assignedAddressCount; - - /** - * Multicast group subscriptions - */ - ZT1_MulticastGroup *multicastSubscriptions; - - /** - * Number of multicast group subscriptions - */ - unsigned int multicastSubscriptionCount; - - /** - * Network name (from network 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 dc6b87a04..7b033181b 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 &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;imulticastSubscriptionCount;++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;istaticIps().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 5693ff49f..b51164a3e 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 e42b02993..ba72a415e 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 f1d107f1f..29262eda6 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(new ZeroTier::Node(now,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigCallback,statusCallback)); + *node = reinterpret_cast(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 fe7045320..5b158228e 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(this), - reinterpret_cast(&addr), - desperation, - data, - len) == 0); - } catch ( ... ) { // callbacks should not throw - return false; - } + return (_wirePacketSendFunction( + reinterpret_cast(this), + reinterpret_cast(&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(this), - nwid, - source.toInt(), - dest.toInt(), - etherType, - vlanId, - data, - len); - } catch ( ... ) {} // callbacks should not throw + _virtualNetworkFrameFunction( + reinterpret_cast(this), + nwid, + source.toInt(), + dest.toInt(), + etherType, + vlanId, + data, + len); } inline SharedPtr network(uint64_t nwid) @@ -167,6 +161,8 @@ public: inline void postEvent(ZT1_Event ev) { _statusCallback(reinterpret_cast(this),ev); } + inline int configureVirtualNetworkPort(uint64_t nwid,const ZT1_VirtualNetworkConfig *nc) { return _virtualNetworkConfigFunction(reinterpret_cast(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