瀏覽代碼

Network now calls port config function as per new API.

Adam Ierymenko 10 年之前
父節點
當前提交
8001b2c0cb
共有 6 個文件被更改,包括 155 次插入68 次删除
  1. 47 23
      include/ZeroTierOne.h
  2. 62 16
      node/Network.cpp
  3. 19 2
      node/Network.hpp
  4. 4 0
      node/NetworkConfig.cpp
  5. 4 4
      node/Node.cpp
  6. 19 23
      node/Node.hpp

+ 47 - 23
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
 	 */
@@ -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);
 
 /**

+ 62 - 16
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

+ 19 - 2
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;
 

+ 4 - 0
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());
 

+ 4 - 4
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;

+ 19 - 23
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