Browse Source

Merge branch 'dev' into edge

Adam Ierymenko 9 years ago
parent
commit
93ab8d46b9
13 changed files with 159 additions and 176 deletions
  1. 1 1
      controller/README.md
  2. 23 16
      include/ZeroTierOne.h
  3. 3 3
      node/IncomingPacket.cpp
  4. 7 6
      node/Network.cpp
  5. 8 1
      node/Network.hpp
  6. 12 8
      node/Node.cpp
  7. 7 4
      node/Node.hpp
  8. 74 95
      node/Peer.cpp
  9. 3 12
      node/Peer.hpp
  10. 3 7
      node/Switch.cpp
  11. 1 8
      node/Switch.hpp
  12. 2 2
      service/ControlPlane.cpp
  13. 15 13
      service/OneService.cpp

+ 1 - 1
controller/README.md

@@ -5,7 +5,7 @@ This folder contains code implementing the node/NetworkController.hpp interface
 
 ### Building
 
-By default this code is not built or included in the client. To build on Linux, BSD, or Mac add ZT\_ENABLE\_NETCONF\_MASTER=1 to the make command line. You'll need the development headers for Sqlite3 installed. They ship as part of OSX and Xcode. On Linux or BSD you'll probably need to install a package.
+By default this code is not built or included in the client. To build on Linux, BSD, or Mac add ZT_\ENABLE_\NETWORK_\CONTROLLER=1 to the make command line. You'll need the development headers for Sqlite3 installed. They ship as part of OSX and Xcode. On Linux or BSD you'll probably need to install a package.
 
 ### Running
 

+ 23 - 16
include/ZeroTierOne.h

@@ -978,11 +978,12 @@ typedef void ZT_Node;
  * PORT_ERROR state.
  */
 typedef int (*ZT_VirtualNetworkConfigFunction)(
-	ZT_Node *,
-	void *,
-	uint64_t,
-	enum ZT_VirtualNetworkConfigOperation,
-	const ZT_VirtualNetworkConfig *);
+	ZT_Node *,                             /* Node */
+	void *,                                /* User ptr */
+	uint64_t,                              /* Network ID */
+	void **,                               /* Modifiable network user PTR */
+	enum ZT_VirtualNetworkConfigOperation, /* Config operation */
+	const ZT_VirtualNetworkConfig *);      /* Network configuration */
 
 /**
  * Function to send a frame out to a virtual network port
@@ -992,15 +993,16 @@ typedef int (*ZT_VirtualNetworkConfigFunction)(
  * (9) frame length.
  */
 typedef void (*ZT_VirtualNetworkFrameFunction)(
-	ZT_Node *,
-	void *,
-	uint64_t,
-	uint64_t,
-	uint64_t,
-	unsigned int,
-	unsigned int,
-	const void *,
-	unsigned int);
+	ZT_Node *,                             /* Node */
+	void *,                                /* User ptr */
+	uint64_t,                              /* Network ID */
+	void **,                               /* Modifiable network user PTR */
+	uint64_t,                              /* Source MAC */
+	uint64_t,                              /* Destination MAC */
+	unsigned int,                          /* Ethernet type */
+	unsigned int,                          /* VLAN ID (0 for none) */
+	const void *,                          /* Frame data */
+	unsigned int);                         /* Frame length */
 
 /**
  * Callback for events
@@ -1245,9 +1247,10 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,vol
  *
  * @param node Node instance
  * @param nwid 64-bit ZeroTier network ID
+ * @param uptr An arbitrary pointer to associate with this network (default: NULL)
  * @return OK (0) or error code if a fatal error condition has occurred
  */
-enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid);
+enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr = (void *)0);
 
 /**
  * Leave a network
@@ -1256,11 +1259,15 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid);
  * to the port config callback with a NULL second parameter to indicate that
  * the port is now deleted.
  *
+ * The uptr parameter is optional and is NULL by default. If it is not NULL,
+ * the pointer it points to is set to this network's uptr on success.
+ *
  * @param node Node instance
  * @param nwid 64-bit network ID
+ * @param uptr Target pointer is set to uptr (if not NULL)
  * @return OK (0) or error code if a fatal error condition has occurred
  */
-enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid);
+enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr = (void **)0);
 
 /**
  * Subscribe to an Ethernet multicast group

+ 3 - 3
node/IncomingPacket.cpp

@@ -548,7 +548,7 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer>
 				}
 
 				const unsigned int payloadLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD;
-				RR->node->putFrame(network->id(),MAC(peer->address(),network->id()),network->mac(),etherType,0,field(ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,payloadLen),payloadLen);
+				RR->node->putFrame(network->id(),network->userPtr(),MAC(peer->address(),network->id()),network->mac(),etherType,0,field(ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,payloadLen),payloadLen);
 			}
 
 			peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP);
@@ -619,7 +619,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P
 				}
 
 				const unsigned int payloadLen = size() - (comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD);
-				RR->node->putFrame(network->id(),from,to,etherType,0,field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD,payloadLen),payloadLen);
+				RR->node->putFrame(network->id(),network->userPtr(),from,to,etherType,0,field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD,payloadLen),payloadLen);
 			}
 
 			peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP);
@@ -888,7 +888,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
 					}
 				}
 
-				RR->node->putFrame(network->id(),from,to.mac(),etherType,0,field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,payloadLen),payloadLen);
+				RR->node->putFrame(network->id(),network->userPtr(),from,to.mac(),etherType,0,field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,payloadLen),payloadLen);
 			}
 
 			if (gatherLimit) {

+ 7 - 6
node/Network.cpp

@@ -45,8 +45,9 @@ namespace ZeroTier {
 
 const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0);
 
-Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
+Network::Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr) :
 	RR(renv),
+	_uptr(uptr),
 	_id(nwid),
 	_mac(renv->identity.address(),nwid),
 	_enabled(true),
@@ -88,7 +89,7 @@ Network::Network(const RuntimeEnvironment *renv,uint64_t nwid) :
 	if (!_portInitialized) {
 		ZT_VirtualNetworkConfig ctmp;
 		_externalConfig(&ctmp);
-		_portError = RR->node->configureVirtualNetworkPort(_id,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
+		_portError = RR->node->configureVirtualNetworkPort(_id,&_uptr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
 		_portInitialized = true;
 	}
 }
@@ -100,11 +101,11 @@ Network::~Network()
 
 	char n[128];
 	if (_destroyed) {
-		RR->node->configureVirtualNetworkPort(_id,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
+		RR->node->configureVirtualNetworkPort(_id,&_uptr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
 		Utils::snprintf(n,sizeof(n),"networks.d/%.16llx.conf",_id);
 		RR->node->dataStoreDelete(n);
 	} else {
-		RR->node->configureVirtualNetworkPort(_id,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp);
+		RR->node->configureVirtualNetworkPort(_id,&_uptr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp);
 	}
 }
 
@@ -173,7 +174,7 @@ bool Network::applyConfiguration(const SharedPtr<NetworkConfig> &conf)
 				portInitialized = _portInitialized;
 				_portInitialized = true;
 			}
-			_portError = RR->node->configureVirtualNetworkPort(_id,(portInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
+			_portError = RR->node->configureVirtualNetworkPort(_id,&_uptr,(portInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP,&ctmp);
 			return true;
 		} else {
 			TRACE("ignored invalid configuration for network %.16llx (configuration contains mismatched network ID or issued-to address)",(unsigned long long)_id);
@@ -331,7 +332,7 @@ void Network::setEnabled(bool enabled)
 		_enabled = enabled;
 		ZT_VirtualNetworkConfig ctmp;
 		_externalConfig(&ctmp);
-		_portError = RR->node->configureVirtualNetworkPort(_id,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE,&ctmp);
+		_portError = RR->node->configureVirtualNetworkPort(_id,&_uptr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE,&ctmp);
 	}
 }
 

+ 8 - 1
node/Network.hpp

@@ -80,8 +80,9 @@ public:
 	 *
 	 * @param renv Runtime environment
 	 * @param nwid Network ID
+	 * @param uptr Arbitrary pointer used by externally-facing API (for user use)
 	 */
-	Network(const RuntimeEnvironment *renv,uint64_t nwid);
+	Network(const RuntimeEnvironment *renv,uint64_t nwid,void *uptr);
 
 	~Network();
 
@@ -331,6 +332,11 @@ public:
 	 */
 	void destroy();
 
+	/**
+	 * @return Pointer to user PTR (modifiable user ptr used in API)
+	 */
+	inline void **userPtr() throw() { return &_uptr; }
+
 	inline bool operator==(const Network &n) const throw() { return (_id == n._id); }
 	inline bool operator!=(const Network &n) const throw() { return (_id != n._id); }
 	inline bool operator<(const Network &n) const throw() { return (_id < n._id); }
@@ -348,6 +354,7 @@ private:
 	std::vector<MulticastGroup> _allMulticastGroups() const;
 
 	const RuntimeEnvironment *RR;
+	void *_uptr;
 	uint64_t _id;
 	MAC _mac; // local MAC address
 	volatile bool _enabled;

+ 12 - 8
node/Node.cpp

@@ -358,24 +358,28 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
 	return ZT_RESULT_OK;
 }
 
-ZT_ResultCode Node::join(uint64_t nwid)
+ZT_ResultCode Node::join(uint64_t nwid,void *uptr)
 {
 	Mutex::Lock _l(_networks_m);
 	SharedPtr<Network> nw = _network(nwid);
 	if(!nw)
-		_networks.push_back(std::pair< uint64_t,SharedPtr<Network> >(nwid,SharedPtr<Network>(new Network(RR,nwid))));
+		_networks.push_back(std::pair< uint64_t,SharedPtr<Network> >(nwid,SharedPtr<Network>(new Network(RR,nwid,uptr))));
 	std::sort(_networks.begin(),_networks.end()); // will sort by nwid since it's the first in a pair<>
 	return ZT_RESULT_OK;
 }
 
-ZT_ResultCode Node::leave(uint64_t nwid)
+ZT_ResultCode Node::leave(uint64_t nwid,void **uptr)
 {
 	std::vector< std::pair< uint64_t,SharedPtr<Network> > > newn;
 	Mutex::Lock _l(_networks_m);
 	for(std::vector< std::pair< uint64_t,SharedPtr<Network> > >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
 		if (n->first != nwid)
 			newn.push_back(*n);
-		else n->second->destroy();
+		else {
+			if (uptr)
+				*uptr = n->second->userPtr();
+			n->second->destroy();
+		}
 	}
 	_networks.swap(newn);
 	return ZT_RESULT_OK;
@@ -839,10 +843,10 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,vol
 	}
 }
 
-enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid)
+enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr)
 {
 	try {
-		return reinterpret_cast<ZeroTier::Node *>(node)->join(nwid);
+		return reinterpret_cast<ZeroTier::Node *>(node)->join(nwid,uptr);
 	} catch (std::bad_alloc &exc) {
 		return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
 	} catch ( ... ) {
@@ -850,10 +854,10 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid)
 	}
 }
 
-enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid)
+enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr)
 {
 	try {
-		return reinterpret_cast<ZeroTier::Node *>(node)->leave(nwid);
+		return reinterpret_cast<ZeroTier::Node *>(node)->leave(nwid,uptr);
 	} catch (std::bad_alloc &exc) {
 		return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
 	} catch ( ... ) {

+ 7 - 4
node/Node.hpp

@@ -96,8 +96,8 @@ public:
 		unsigned int frameLength,
 		volatile uint64_t *nextBackgroundTaskDeadline);
 	ZT_ResultCode processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
-	ZT_ResultCode join(uint64_t nwid);
-	ZT_ResultCode leave(uint64_t nwid);
+	ZT_ResultCode join(uint64_t nwid,void *uptr);
+	ZT_ResultCode leave(uint64_t nwid,void **uptr);
 	ZT_ResultCode multicastSubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
 	ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
 	uint64_t address() const;
@@ -169,6 +169,7 @@ public:
 	 * Enqueue a frame to be injected into a tap device (port)
 	 *
 	 * @param nwid Network ID
+	 * @param nuptr Network user ptr
 	 * @param source Source MAC
 	 * @param dest Destination MAC
 	 * @param etherType 16-bit ethernet type
@@ -176,12 +177,13 @@ public:
 	 * @param data Frame data
 	 * @param len Frame length
 	 */
-	inline void putFrame(uint64_t nwid,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
+	inline void putFrame(uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
 	{
 		_virtualNetworkFrameFunction(
 			reinterpret_cast<ZT_Node *>(this),
 			_uPtr,
 			nwid,
+			nuptr,
 			source.toInt(),
 			dest.toInt(),
 			etherType,
@@ -249,10 +251,11 @@ public:
 	 * Update virtual network port configuration
 	 *
 	 * @param nwid Network ID
+	 * @param nuptr Network user ptr
 	 * @param op Configuration operation
 	 * @param nc Network configuration
 	 */
-	inline int configureVirtualNetworkPort(uint64_t nwid,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,nwid,op,nc); }
+	inline int configureVirtualNetworkPort(uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { return _virtualNetworkConfigFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,nwid,nuptr,op,nc); }
 
 	/**
 	 * @return True if we appear to be online

+ 74 - 95
node/Peer.cpp

@@ -126,87 +126,77 @@ void Peer::received(
 #endif
 
 	const uint64_t now = RR->node->now();
-	bool needMulticastGroupAnnounce = false;
-
-	{	// begin _lock
-		Mutex::Lock _l(_lock);
-
-		_lastReceive = now;
-		if ((verb == Packet::VERB_FRAME)||(verb == Packet::VERB_EXT_FRAME))
-			_lastUnicastFrame = now;
-		else if (verb == Packet::VERB_MULTICAST_FRAME)
-			_lastMulticastFrame = now;
-
-		if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
-			_lastAnnouncedTo = now;
-			needMulticastGroupAnnounce = true;
-		}
-
-		if (hops == 0) {
-			bool pathIsConfirmed = false;
-			unsigned int np = _numPaths;
-			for(unsigned int p=0;p<np;++p) {
-				if ((_paths[p].address() == remoteAddr)&&(_paths[p].localAddress() == localAddr)) {
-					_paths[p].received(now);
+	_lastReceive = now;
+	if ((verb == Packet::VERB_FRAME)||(verb == Packet::VERB_EXT_FRAME))
+		_lastUnicastFrame = now;
+	else if (verb == Packet::VERB_MULTICAST_FRAME)
+		_lastMulticastFrame = now;
+
+	if (hops == 0) {
+		bool pathIsConfirmed = false;
+		unsigned int np = _numPaths;
+		for(unsigned int p=0;p<np;++p) {
+			if ((_paths[p].address() == remoteAddr)&&(_paths[p].localAddress() == localAddr)) {
+				_paths[p].received(now);
 #ifdef ZT_ENABLE_CLUSTER
-					_paths[p].setClusterSuboptimal(suboptimalPath);
+				_paths[p].setClusterSuboptimal(suboptimalPath);
 #endif
-					pathIsConfirmed = true;
-					break;
-				}
+				pathIsConfirmed = true;
+				break;
 			}
+		}
 
-			if ((!pathIsConfirmed)&&(RR->node->shouldUsePathForZeroTierTraffic(localAddr,remoteAddr))) {
-				if (verb == Packet::VERB_OK) {
-
-					Path *slot = (Path *)0;
-					if (np < ZT_MAX_PEER_NETWORK_PATHS) {
-						slot = &(_paths[np++]);
-					} else {
-						uint64_t slotLRmin = 0xffffffffffffffffULL;
-						for(unsigned int p=0;p<ZT_MAX_PEER_NETWORK_PATHS;++p) {
-							if (!_paths[p].active(now)) {
-								slot = &(_paths[p]);
-								break;
-							} else if (_paths[p].lastReceived() <= slotLRmin) {
-								slotLRmin = _paths[p].lastReceived();
-								slot = &(_paths[p]);
-							}
+		if ((!pathIsConfirmed)&&(RR->node->shouldUsePathForZeroTierTraffic(localAddr,remoteAddr))) {
+			if (verb == Packet::VERB_OK) {
+
+				Path *slot = (Path *)0;
+				if (np < ZT_MAX_PEER_NETWORK_PATHS) {
+					slot = &(_paths[np++]);
+				} else {
+					uint64_t slotLRmin = 0xffffffffffffffffULL;
+					for(unsigned int p=0;p<ZT_MAX_PEER_NETWORK_PATHS;++p) {
+						if (!_paths[p].active(now)) {
+							slot = &(_paths[p]);
+							break;
+						} else if (_paths[p].lastReceived() <= slotLRmin) {
+							slotLRmin = _paths[p].lastReceived();
+							slot = &(_paths[p]);
 						}
 					}
-					if (slot) {
-						*slot = Path(localAddr,remoteAddr);
-						slot->received(now);
+				}
+				if (slot) {
+					*slot = Path(localAddr,remoteAddr);
+					slot->received(now);
 #ifdef ZT_ENABLE_CLUSTER
-						slot->setClusterSuboptimal(suboptimalPath);
+					slot->setClusterSuboptimal(suboptimalPath);
 #endif
-						_numPaths = np;
-					}
+					_numPaths = np;
+				}
 
 #ifdef ZT_ENABLE_CLUSTER
-					if (RR->cluster)
-						RR->cluster->broadcastHavePeer(_id);
+				if (RR->cluster)
+					RR->cluster->broadcastHavePeer(_id);
 #endif
 
-				} else {
+			} else {
 
-					TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),remoteAddr.toString().c_str());
-
-					if ( (_vProto >= 5) && ( !((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0)) ) ) {
-						// 1.1.1 and newer nodes support ECHO, which is smaller -- but 1.1.0 has a bug so use HELLO there too
-						Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
-						outp.armor(_key,true);
-						RR->node->putPacket(localAddr,remoteAddr,outp.data(),outp.size());
-					} else {
-						sendHELLO(localAddr,remoteAddr,now);
-					}
+				TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),remoteAddr.toString().c_str());
 
+				if ( (_vProto >= 5) && ( !((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0)) ) ) {
+					// 1.1.1 and newer nodes support ECHO, which is smaller -- but 1.1.0 has a bug so use HELLO there too
+					Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
+					outp.armor(_key,true);
+					RR->node->putPacket(localAddr,remoteAddr,outp.data(),outp.size());
+				} else {
+					sendHELLO(localAddr,remoteAddr,now);
 				}
+
 			}
 		}
-	}	// end _lock
+	}
 
-	if (needMulticastGroupAnnounce) {
+	if ((now - _lastAnnouncedTo) >= ((ZT_MULTICAST_LIKE_EXPIRE / 2) - 1000)) {
+		_lastAnnouncedTo = now;
 		const std::vector< SharedPtr<Network> > networks(RR->node->allNetworks());
 		for(std::vector< SharedPtr<Network> >::const_iterator n(networks.begin());n!=networks.end();++n)
 			(*n)->tryAnnounceMulticastGroupsTo(SharedPtr<Peer>(this));
@@ -215,8 +205,6 @@ void Peer::received(
 
 void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now,unsigned int ttl)
 {
-	// _lock not required here since _id is immutable and nothing else is accessed
-
 	Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO);
 	outp.append((unsigned char)ZT_PROTO_VERSION);
 	outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
@@ -236,7 +224,6 @@ bool Peer::doPingAndKeepalive(uint64_t now,int inetAddressFamily)
 {
 	Path *p = (Path *)0;
 
-	Mutex::Lock _l(_lock);
 	if (inetAddressFamily != 0) {
 		p = _getBestPath(now,inetAddressFamily);
 	} else {
@@ -271,8 +258,6 @@ void Peer::pushDirectPaths(Path *path,uint64_t now,bool force)
 		return;
 #endif
 
-	Mutex::Lock _l(_lock);
-
 	if (((now - _lastDirectPathPushSent) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force)) {
 		_lastDirectPathPushSent = now;
 
@@ -333,7 +318,6 @@ void Peer::pushDirectPaths(Path *path,uint64_t now,bool force)
 
 bool Peer::resetWithinScope(InetAddress::IpScope scope,uint64_t now)
 {
-	Mutex::Lock _l(_lock);
 	unsigned int np = _numPaths;
 	unsigned int x = 0;
 	unsigned int y = 0;
@@ -353,7 +337,6 @@ bool Peer::resetWithinScope(InetAddress::IpScope scope,uint64_t now)
 
 void Peer::getBestActiveAddresses(uint64_t now,InetAddress &v4,InetAddress &v6) const
 {
-	Mutex::Lock _l(_lock);
 	uint64_t bestV4 = 0,bestV6 = 0;
 	for(unsigned int p=0,np=_numPaths;p<np;++p) {
 		if (_paths[p].active(now)) {
@@ -377,7 +360,7 @@ void Peer::getBestActiveAddresses(uint64_t now,InetAddress &v4,InetAddress &v6)
 
 bool Peer::networkMembershipCertificatesAgree(uint64_t nwid,const CertificateOfMembership &com) const
 {
-	Mutex::Lock _l(_lock);
+	Mutex::Lock _l(_networkComs_m);
 	const _NetworkCom *ourCom = _networkComs.get(nwid);
 	if (ourCom)
 		return ourCom->com.agreesWith(com);
@@ -392,7 +375,7 @@ bool Peer::validateAndSetNetworkMembershipCertificate(uint64_t nwid,const Certif
 
 	// Return true if we already have this *exact* COM
 	{
-		Mutex::Lock _l(_lock);
+		Mutex::Lock _l(_networkComs_m);
 		_NetworkCom *ourCom = _networkComs.get(nwid);
 		if ((ourCom)&&(ourCom->com == com))
 			return true;
@@ -432,7 +415,7 @@ bool Peer::validateAndSetNetworkMembershipCertificate(uint64_t nwid,const Certif
 
 	// If we made it past all those checks, add or update cert in our cert info store
 	{
-		Mutex::Lock _l(_lock);
+		Mutex::Lock _l(_networkComs_m);
 		_networkComs.set(nwid,_NetworkCom(RR->node->now(),com));
 	}
 
@@ -441,7 +424,7 @@ bool Peer::validateAndSetNetworkMembershipCertificate(uint64_t nwid,const Certif
 
 bool Peer::needsOurNetworkMembershipCertificate(uint64_t nwid,uint64_t now,bool updateLastPushedTime)
 {
-	Mutex::Lock _l(_lock);
+	Mutex::Lock _l(_networkComs_m);
 	uint64_t &lastPushed = _lastPushedComs[nwid];
 	const uint64_t tmp = lastPushed;
 	if (updateLastPushedTime)
@@ -451,8 +434,6 @@ bool Peer::needsOurNetworkMembershipCertificate(uint64_t nwid,uint64_t now,bool
 
 void Peer::clean(uint64_t now)
 {
-	Mutex::Lock _l(_lock);
-
 	{
 		unsigned int np = _numPaths;
 		unsigned int x = 0;
@@ -466,30 +447,30 @@ void Peer::clean(uint64_t now)
 	}
 
 	{
-		uint64_t *k = (uint64_t *)0;
-		_NetworkCom *v = (_NetworkCom *)0;
-		Hashtable< uint64_t,_NetworkCom >::Iterator i(_networkComs);
-		while (i.next(k,v)) {
-			if ( (!RR->node->belongsToNetwork(*k)) && ((now - v->ts) >= ZT_PEER_NETWORK_COM_EXPIRATION) )
-				_networkComs.erase(*k);
+		Mutex::Lock _l(_networkComs_m);
+		{
+			uint64_t *k = (uint64_t *)0;
+			_NetworkCom *v = (_NetworkCom *)0;
+			Hashtable< uint64_t,_NetworkCom >::Iterator i(_networkComs);
+			while (i.next(k,v)) {
+				if ( (!RR->node->belongsToNetwork(*k)) && ((now - v->ts) >= ZT_PEER_NETWORK_COM_EXPIRATION) )
+					_networkComs.erase(*k);
+			}
 		}
-	}
-
-	{
-		uint64_t *k = (uint64_t *)0;
-		uint64_t *v = (uint64_t *)0;
-		Hashtable< uint64_t,uint64_t >::Iterator i(_lastPushedComs);
-		while (i.next(k,v)) {
-			if ((now - *v) > (ZT_NETWORK_AUTOCONF_DELAY * 2))
-				_lastPushedComs.erase(*k);
+		{
+			uint64_t *k = (uint64_t *)0;
+			uint64_t *v = (uint64_t *)0;
+			Hashtable< uint64_t,uint64_t >::Iterator i(_lastPushedComs);
+			while (i.next(k,v)) {
+				if ((now - *v) > (ZT_NETWORK_AUTOCONF_DELAY * 2))
+					_lastPushedComs.erase(*k);
+			}
 		}
 	}
 }
 
 bool Peer::_checkPath(Path &p,const uint64_t now)
 {
-	// assumes _lock is locked
-
 	if (!p.active(now))
 		return false;
 
@@ -536,7 +517,6 @@ bool Peer::_checkPath(Path &p,const uint64_t now)
 
 Path *Peer::_getBestPath(const uint64_t now)
 {
-	// assumes _lock is locked
 	Path *bestPath = (Path *)0;
 	uint64_t bestPathScore = 0;
 	for(unsigned int i=0;i<_numPaths;++i) {
@@ -551,7 +531,6 @@ Path *Peer::_getBestPath(const uint64_t now)
 
 Path *Peer::_getBestPath(const uint64_t now,int inetAddressFamily)
 {
-	// assumes _lock is locked
 	Path *bestPath = (Path *)0;
 	uint64_t bestPathScore = 0;
 	for(unsigned int i=0;i<_numPaths;++i) {

+ 3 - 12
node/Peer.hpp

@@ -134,11 +134,7 @@ public:
 	 * @param now Current time
 	 * @return Best path or NULL if there are no active direct paths
 	 */
-	inline Path *getBestPath(uint64_t now)
-	{
-		Mutex::Lock _l(_lock);
-		return _getBestPath(now);
-	}
+	inline Path *getBestPath(uint64_t now) { return _getBestPath(now); }
 
 	/**
 	 * Send via best path
@@ -195,7 +191,6 @@ public:
 	inline std::vector<Path> paths() const
 	{
 		std::vector<Path> pp;
-		Mutex::Lock _l(_lock);
 		for(unsigned int p=0,np=_numPaths;p<np;++p)
 			pp.push_back(_paths[p]);
 		return pp;
@@ -277,7 +272,6 @@ public:
 	 */
 	inline bool hasActiveDirectPath(uint64_t now) const
 	{
-		Mutex::Lock _l(_lock);
 		for(unsigned int p=0;p<_numPaths;++p) {
 			if (_paths[p].active(now))
 				return true;
@@ -292,7 +286,6 @@ public:
 	 */
 	inline bool hasClusterOptimalPath(uint64_t now) const
 	{
-		Mutex::Lock _l(_lock);
 		for(unsigned int p=0,np=_numPaths;p<np;++p) {
 			if ((_paths[p].active(now))&&(!_paths[p].isClusterSuboptimal()))
 				return true;
@@ -308,7 +301,6 @@ public:
 	 */
 	inline bool hasActivePathTo(uint64_t now,const InetAddress &addr) const
 	{
-		Mutex::Lock _l(_lock);
 		for(unsigned int p=0;p<_numPaths;++p) {
 			if ((_paths[p].active(now))&&(_paths[p].address() == addr))
 				return true;
@@ -410,7 +402,6 @@ public:
 	 */
 	inline bool shouldRespondToDirectPathPush(const uint64_t now)
 	{
-		Mutex::Lock _l(_lock);
 		if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME)
 			++_directPathPushCutoffCount;
 		else _directPathPushCutoffCount = 0;
@@ -441,7 +432,7 @@ public:
 	template<unsigned int C>
 	inline void serialize(Buffer<C> &b) const
 	{
-		Mutex::Lock _l(_lock);
+		Mutex::Lock _l(_networkComs_m);
 
 		const unsigned int recSizePos = b.size();
 		b.addSize(4); // space for uint32_t field length
@@ -599,8 +590,8 @@ private:
 	};
 	Hashtable<uint64_t,_NetworkCom> _networkComs;
 	Hashtable<uint64_t,uint64_t> _lastPushedComs;
+	Mutex _networkComs_m;
 
-	Mutex _lock;
 	AtomicCounter __refCount;
 };
 

+ 3 - 7
node/Switch.cpp

@@ -89,6 +89,8 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
 			Address beaconAddr(reinterpret_cast<const char *>(data) + 8,5);
 			if (beaconAddr == RR->identity.address())
 				return;
+			if (!RR->node->shouldUsePathForZeroTierTraffic(localAddr,fromAddr))
+				return;
 			SharedPtr<Peer> peer(RR->topology->getPeer(beaconAddr));
 			if (peer) { // we'll only respond to beacons from known peers
 				const uint64_t now = RR->node->now();
@@ -214,7 +216,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 									adv[42] = (checksum >> 8) & 0xff;
 									adv[43] = checksum & 0xff;
 
-									RR->node->putFrame(network->id(),atPeerMac,from,ZT_ETHERTYPE_IPV6,0,adv,72);
+									RR->node->putFrame(network->id(),network->userPtr(),atPeerMac,from,ZT_ETHERTYPE_IPV6,0,adv,72);
 									return; // stop processing: we have handled this frame with a spoofed local reply so no need to send it anywhere
 								}
 							}
@@ -449,12 +451,6 @@ void Switch::requestWhois(const Address &addr)
 		_sendWhoisRequest(addr,(const Address *)0,0);
 }
 
-void Switch::cancelWhoisRequest(const Address &addr)
-{
-	Mutex::Lock _l(_outstandingWhoisRequests_m);
-	_outstandingWhoisRequests.erase(addr);
-}
-
 void Switch::doAnythingWaitingForPeer(const SharedPtr<Peer> &peer)
 {
 	{	// cancel pending WHOIS since we now know this peer

+ 1 - 8
node/Switch.hpp

@@ -138,13 +138,6 @@ public:
 	 */
 	void requestWhois(const Address &addr);
 
-	/**
-	 * Cancel WHOIS for an address
-	 *
-	 * @param addr Address to cancel
-	 */
-	void cancelWhoisRequest(const Address &addr);
-
 	/**
 	 * Run any processes that are waiting for this peer's identity
 	 *
@@ -174,7 +167,7 @@ private:
 	const RuntimeEnvironment *const RR;
 	uint64_t _lastBeaconResponse;
 
-	// Outsanding WHOIS requests and how many retries they've undergone
+	// Outstanding WHOIS requests and how many retries they've undergone
 	struct WhoisRequest
 	{
 		WhoisRequest() : lastSent(0),retries(0) {}

+ 2 - 2
service/ControlPlane.cpp

@@ -506,7 +506,7 @@ unsigned int ControlPlane::handleRequest(
 			} else if (ps[0] == "network") {
 				if (ps.size() == 2) {
 					uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str());
-					_node->join(wantnw); // does nothing if we are a member
+					_node->join(wantnw,(void *)0); // does nothing if we are a member
 					ZT_VirtualNetworkList *nws = _node->networks();
 					if (nws) {
 						for(unsigned long i=0;i<nws->networkCount;++i) {
@@ -546,7 +546,7 @@ unsigned int ControlPlane::handleRequest(
 						uint64_t wantnw = Utils::hexStrToU64(ps[1].c_str());
 						for(unsigned long i=0;i<nws->networkCount;++i) {
 							if (nws->networks[i].nwid == wantnw) {
-								_node->leave(wantnw);
+								_node->leave(wantnw,(void **)0);
 								responseBody = "true";
 								responseContentType = "application/json";
 								scode = 200;

+ 15 - 13
service/OneService.cpp

@@ -391,12 +391,12 @@ static std::string _trimString(const std::string &s)
 
 class OneServiceImpl;
 
-static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,uint64_t nwid,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf);
+static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf);
 static void SnodeEventCallback(ZT_Node *node,void *uptr,enum ZT_Event event,const void *metaData);
 static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize);
 static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,const char *name,const void *data,unsigned long len,int secure);
 static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl);
-static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,uint64_t nwid,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
+static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
 static int SnodePathCheckFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr);
 
 #ifdef ZT_ENABLE_CLUSTER
@@ -695,7 +695,7 @@ public:
 				for(std::vector<std::string>::iterator f(networksDotD.begin());f!=networksDotD.end();++f) {
 					std::size_t dot = f->find_last_of('.');
 					if ((dot == 16)&&(f->substr(16) == ".conf"))
-						_node->join(Utils::hexStrToU64(f->substr(0,dot).c_str()));
+						_node->join(Utils::hexStrToU64(f->substr(0,dot).c_str()),(void *)0);
 				}
 			}
 
@@ -1131,7 +1131,7 @@ public:
 	inline void phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len) {}
 	inline void phyOnUnixWritable(PhySocket *sock,void **uptr) {}
 
-	inline int nodeVirtualNetworkConfigFunction(uint64_t nwid,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwc)
+	inline int nodeVirtualNetworkConfigFunction(uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwc)
 	{
 		Mutex::Lock _l(_taps_m);
 		std::map< uint64_t,EthernetTap * >::iterator t(_taps.find(nwid));
@@ -1150,6 +1150,7 @@ public:
 							friendlyName,
 							StapFrameHandler,
 							(void *)this))).first;
+						*nuptr = (void *)t->second;
 					} catch (std::exception &exc) {
 #ifdef __WINDOWS__
 						FILE *tapFailLog = fopen((_homePath + ZT_PATH_SEPARATOR_S"port_error_log.txt").c_str(),"a");
@@ -1197,6 +1198,7 @@ public:
 #ifdef __WINDOWS__
 					std::string winInstanceId(t->second->instanceId());
 #endif
+					*nuptr = (void *)0;
 					delete t->second;
 					_taps.erase(t);
 					_tapAssignedIps.erase(nwid);
@@ -1387,12 +1389,12 @@ public:
 		return result;
 	}
 
-	inline void nodeVirtualNetworkFrameFunction(uint64_t nwid,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
+	inline void nodeVirtualNetworkFrameFunction(uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
 	{
-		Mutex::Lock _l(_taps_m);
-		std::map< uint64_t,EthernetTap * >::const_iterator t(_taps.find(nwid));
-		if (t != _taps.end())
-			t->second->put(MAC(sourceMac),MAC(destMac),etherType,data,len);
+		EthernetTap *tap = reinterpret_cast<EthernetTap *>(*nuptr);
+		if (!tap)
+			return;
+		tap->put(MAC(sourceMac),MAC(destMac),etherType,data,len);
 	}
 
 	inline int nodePathCheckFunction(const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr)
@@ -1533,8 +1535,8 @@ public:
 	Mutex _run_m;
 };
 
-static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,uint64_t nwid,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf)
-{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeVirtualNetworkConfigFunction(nwid,op,nwconf); }
+static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf)
+{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeVirtualNetworkConfigFunction(nwid,nuptr,op,nwconf); }
 static void SnodeEventCallback(ZT_Node *node,void *uptr,enum ZT_Event event,const void *metaData)
 { reinterpret_cast<OneServiceImpl *>(uptr)->nodeEventCallback(event,metaData); }
 static long SnodeDataStoreGetFunction(ZT_Node *node,void *uptr,const char *name,void *buf,unsigned long bufSize,unsigned long readIndex,unsigned long *totalSize)
@@ -1543,8 +1545,8 @@ static int SnodeDataStorePutFunction(ZT_Node *node,void *uptr,const char *name,c
 { return reinterpret_cast<OneServiceImpl *>(uptr)->nodeDataStorePutFunction(name,data,len,secure); }
 static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl)
 { return reinterpret_cast<OneServiceImpl *>(uptr)->nodeWirePacketSendFunction(localAddr,addr,data,len,ttl); }
-static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,uint64_t nwid,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
-{ reinterpret_cast<OneServiceImpl *>(uptr)->nodeVirtualNetworkFrameFunction(nwid,sourceMac,destMac,etherType,vlanId,data,len); }
+static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
+{ reinterpret_cast<OneServiceImpl *>(uptr)->nodeVirtualNetworkFrameFunction(nwid,nuptr,sourceMac,destMac,etherType,vlanId,data,len); }
 static int SnodePathCheckFunction(ZT_Node *node,void *uptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr)
 { return reinterpret_cast<OneServiceImpl *>(uptr)->nodePathCheckFunction(localAddr,remoteAddr); }