Parcourir la source

It basically works... at least on current controllers.

Adam Ierymenko il y a 9 ans
Parent
commit
2cdda38dc4
7 fichiers modifiés avec 74 ajouts et 48 suppressions
  1. 10 0
      include/ZeroTierOne.h
  2. 1 6
      node/Membership.cpp
  3. 28 18
      node/Network.cpp
  4. 2 0
      node/Network.hpp
  5. 1 1
      node/OutboundMulticast.cpp
  6. 29 22
      node/Switch.cpp
  7. 3 1
      one.cpp

+ 10 - 0
include/ZeroTierOne.h

@@ -169,6 +169,16 @@ extern "C" {
  */
 #define ZT_RULE_PACKET_CHARACTERISTICS_INBOUND 0x8000000000000000ULL
 
+/**
+ * Packet characteristics flag: multicast or broadcast destination MAC
+ */
+#define ZT_RULE_PACKET_CHARACTERISTICS_MULTICAST 0x4000000000000000ULL
+
+/**
+ * Packet characteristics flag: broadcast destination MAC
+ */
+#define ZT_RULE_PACKET_CHARACTERISTICS_BROADCAST 0x2000000000000000ULL
+
 /**
  * Packet characteristics flag: TCP left-most reserved bit
  */

+ 1 - 6
node/Membership.cpp

@@ -81,8 +81,7 @@ bool Membership::sendCredentialsIfNeeded(const RuntimeEnvironment *RR,const uint
 
 int Membership::addCredential(const RuntimeEnvironment *RR,const CertificateOfMembership &com)
 {
-	if (com.issuedTo() != RR->identity.address())
-		return -1;
+	TRACE("addCredential(COM) for %.16llx signed by %s issued to %s",com.networkId(),com.signedBy().toString().c_str(),com.issuedTo().toString().c_str());
 	if (_com == com)
 		return 0;
 	const int vr = com.verify(RR);
@@ -93,8 +92,6 @@ int Membership::addCredential(const RuntimeEnvironment *RR,const CertificateOfMe
 
 int Membership::addCredential(const RuntimeEnvironment *RR,const Tag &tag)
 {
-	if (tag.issuedTo() != RR->identity.address())
-		return -1;
 	TState *t = _tags.get(tag.id());
 	if ((t)&&(t->lastReceived != 0)&&(t->tag == tag))
 		return 0;
@@ -112,8 +109,6 @@ int Membership::addCredential(const RuntimeEnvironment *RR,const Tag &tag)
 
 int Membership::addCredential(const RuntimeEnvironment *RR,const Capability &cap)
 {
-	if (cap.issuedTo() != RR->identity.address())
-		return -1;
 	std::map<uint32_t,CState>::iterator c(_caps.find(cap.id()));
 	if ((c != _caps.end())&&(c->second.lastReceived != 0)&&(c->second.cap == cap))
 		return 0;

+ 28 - 18
node/Network.cpp

@@ -102,6 +102,7 @@ static bool _ipv6GetPayload(const uint8_t *frameData,unsigned int frameLen,unsig
 // 0 == no match, -1 == match/drop, 1 == match/accept
 static int _doZtFilter(
 	const RuntimeEnvironment *RR,
+	const bool noRedirect,
 	const NetworkConfig &nconf,
 	const bool inbound,
 	const Address &ztSource,
@@ -154,15 +155,17 @@ static int _doZtFilter(
 				break;
 			case ZT_NETWORK_RULE_ACTION_TEE:
 			case ZT_NETWORK_RULE_ACTION_REDIRECT: {
-				Packet outp(Address(rules[rn].v.fwd.address),RR->identity.address(),Packet::VERB_EXT_FRAME);
-				outp.append(nconf.networkId);
-				outp.append((uint8_t)( ((rt == ZT_NETWORK_RULE_ACTION_REDIRECT) ? 0x04 : 0x02) | (inbound ? 0x08 : 0x00) ));
-				macDest.appendTo(outp);
-				macSource.appendTo(outp);
-				outp.append((uint16_t)etherType);
-				outp.append(frameData,(rules[rn].v.fwd.length != 0) ? ((frameLen < (unsigned int)rules[rn].v.fwd.length) ? frameLen : (unsigned int)rules[rn].v.fwd.length) : frameLen);
-				outp.compress();
-				RR->sw->send(outp,true);
+				if (!noRedirect) {
+					Packet outp(Address(rules[rn].v.fwd.address),RR->identity.address(),Packet::VERB_EXT_FRAME);
+					outp.append(nconf.networkId);
+					outp.append((uint8_t)( ((rt == ZT_NETWORK_RULE_ACTION_REDIRECT) ? 0x04 : 0x02) | (inbound ? 0x08 : 0x00) ));
+					macDest.appendTo(outp);
+					macSource.appendTo(outp);
+					outp.append((uint16_t)etherType);
+					outp.append(frameData,(rules[rn].v.fwd.length != 0) ? ((frameLen < (unsigned int)rules[rn].v.fwd.length) ? frameLen : (unsigned int)rules[rn].v.fwd.length) : frameLen);
+					outp.compress();
+					RR->sw->send(outp,true);
+				}
 
 				if (rt == ZT_NETWORK_RULE_ACTION_REDIRECT) {
 					return -1; // match, drop packet (we redirected it)
@@ -318,6 +321,8 @@ static int _doZtFilter(
 				break;
 			case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: {
 				uint64_t cf = (inbound) ? ZT_RULE_PACKET_CHARACTERISTICS_INBOUND : 0ULL;
+				if (macDest.isMulticast()) cf |= ZT_RULE_PACKET_CHARACTERISTICS_MULTICAST;
+				if (macDest.isBroadcast()) cf |= ZT_RULE_PACKET_CHARACTERISTICS_BROADCAST;
 				if ((etherType == ZT_ETHERTYPE_IPV4)&&(frameLen >= 20)&&(frameData[9] == 0x06)) {
 					const unsigned int headerLen = 4 * (frameData[0] & 0xf);
 					cf |= (uint64_t)frameData[headerLen + 13];
@@ -456,6 +461,7 @@ Network::~Network()
 }
 
 bool Network::filterOutgoingPacket(
+	const bool noRedirect,
 	const Address &ztSource,
 	const Address &ztDest,
 	const MAC &macSource,
@@ -475,21 +481,23 @@ bool Network::filterOutgoingPacket(
 	Membership &m = _memberships[ztDest];
 	const unsigned int remoteTagCount = m.getAllTags(_config,remoteTagIds,remoteTagValues,ZT_MAX_NETWORK_TAGS);
 
-	switch(_doZtFilter(RR,_config,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) {
+	switch(_doZtFilter(RR,noRedirect,_config,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) {
 		case -1:
 			return false;
 		case 1:
-			m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,(const Capability *)0,relevantLocalTags,relevantLocalTagCount);
+			if (ztDest)
+				m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,(const Capability *)0,relevantLocalTags,relevantLocalTagCount);
 			return true;
 	}
 
 	for(unsigned int c=0;c<_config.capabilityCount;++c) {
 		relevantLocalTagCount = 0;
-		switch (_doZtFilter(RR,_config,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.capabilities[c].rules(),_config.capabilities[c].ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) {
+		switch (_doZtFilter(RR,noRedirect,_config,false,ztSource,ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.capabilities[c].rules(),_config.capabilities[c].ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) {
 			case -1:
 				return false;
 			case 1:
-				m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,&(_config.capabilities[c]),relevantLocalTags,relevantLocalTagCount);
+				if (ztDest)
+					m.sendCredentialsIfNeeded(RR,RR->node->now(),ztDest,_config.com,&(_config.capabilities[c]),relevantLocalTags,relevantLocalTagCount);
 				return true;
 		}
 	}
@@ -517,7 +525,7 @@ bool Network::filterIncomingPacket(
 	Membership &m = _memberships[ztDest];
 	const unsigned int remoteTagCount = m.getAllTags(_config,remoteTagIds,remoteTagValues,ZT_MAX_NETWORK_TAGS);
 
-	switch (_doZtFilter(RR,_config,true,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) {
+	switch (_doZtFilter(RR,false,_config,true,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) {
 		case -1:
 			return false;
 		case 1:
@@ -528,7 +536,7 @@ bool Network::filterIncomingPacket(
 	const Capability *c;
 	while ((c = mci.next(_config))) {
 		relevantLocalTagCount = 0;
-		switch(_doZtFilter(RR,_config,false,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,c->rules(),c->ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) {
+		switch(_doZtFilter(RR,false,_config,false,sourcePeer->address(),ztDest,macSource,macDest,frameData,frameLen,etherType,vlanId,c->rules(),c->ruleCount(),_config.tags,_config.tagCount,remoteTagIds,remoteTagValues,remoteTagCount,relevantLocalTags,relevantLocalTagCount)) {
 			case -1:
 				return false;
 			case 1:
@@ -698,6 +706,8 @@ void Network::requestConfiguration()
 		return;
 	_lastRequestedConfiguration = RR->node->now();
 
+	const Address ctrl(controller());
+
 	Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> rmd;
 	rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION,(uint64_t)ZT_NETWORKCONFIG_VERSION);
 	rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION,(uint64_t)ZT_PROTO_VERSION);
@@ -710,7 +720,7 @@ void Network::requestConfiguration()
 	rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_MAX_NETWORK_TAGS,(uint64_t)ZT_MAX_NETWORK_TAGS);
 	rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS,(uint64_t)0);
 
-	if (controller() == RR->identity.address()) {
+	if (ctrl == RR->identity.address()) {
 		if (RR->localNetworkController) {
 			NetworkConfig nconf;
 			switch(RR->localNetworkController->doNetworkConfigRequest(InetAddress(),RR->identity,RR->identity,_id,rmd,nconf)) {
@@ -732,9 +742,9 @@ void Network::requestConfiguration()
 		}
 	}
 
-	TRACE("requesting netconf for network %.16llx from controller %s",(unsigned long long)_id,controller().toString().c_str());
+	TRACE("requesting netconf for network %.16llx from controller %s",(unsigned long long)_id,ctrl.toString().c_str());
 
-	Packet outp(controller(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
+	Packet outp(ctrl,RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
 	outp.append((uint64_t)_id);
 	const unsigned int rmdSize = rmd.sizeBytes();
 	outp.append((uint16_t)rmdSize);

+ 2 - 0
node/Network.hpp

@@ -86,6 +86,7 @@ public:
 	 * certain actions may be taken such as pushing credentials to ztDest and
 	 * sending a copy of the packet to a TEE or REDIRECT target.
 	 *
+	 * @param noRedirect If true, do not TEE or REDIRECT -- this is set for secondary filtrations done in multicast and bridge send paths
 	 * @param ztSource Source ZeroTier address
 	 * @param ztDest Destination ZeroTier address
 	 * @param macSource Ethernet layer source address
@@ -97,6 +98,7 @@ public:
 	 * @return True if packet should be sent to destination peer
 	 */
 	bool filterOutgoingPacket(
+		const bool noRedirect,
 		const Address &ztSource,
 		const Address &ztDest,
 		const MAC &macSource,

+ 1 - 1
node/OutboundMulticast.cpp

@@ -86,7 +86,7 @@ void OutboundMulticast::init(
 void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,const Address &toAddr)
 {
 	const SharedPtr<Network> nw(RR->node->network(_nwid));
-	if ((nw)&&(nw->filterOutgoingPacket(RR->identity.address(),toAddr,_macSrc,_macDest,_frameData,_frameLen,_etherType,0))) {
+	if ((nw)&&(nw->filterOutgoingPacket(true,RR->identity.address(),toAddr,_macSrc,_macDest,_frameData,_frameLen,_etherType,0))) {
 		//TRACE(">>MC %.16llx -> %s",(unsigned long long)this,toAddr.toString().c_str());
 		_packet.newInitializationVector();
 		_packet.setDestination(toAddr);

+ 29 - 22
node/Switch.cpp

@@ -437,7 +437,11 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 
 		//TRACE("%.16llx: MULTICAST %s -> %s %s %u",network->id(),from.toString().c_str(),mg.toString().c_str(),etherTypeName(etherType),len);
 
-		if (!network->filterOutgoingPacket(RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) {
+		// We filter with a NULL destination ZeroTier address first. Filtrations
+		// for each ZT destination are also done in OutboundMulticast, but these
+		// set noRedirect to true. This prevents multiple TEEs and REDIRECTs for
+		// multicast packets.
+		if (!network->filterOutgoingPacket(false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) {
 			TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
 			return;
 		}
@@ -452,17 +456,13 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 			etherType,
 			data,
 			len);
-
-		return;
-	}
-
-	if (to[0] == MAC::firstOctetForNetwork(network->id())) {
+	} else if (to[0] == MAC::firstOctetForNetwork(network->id())) {
 		// Destination is another ZeroTier peer on the same network
 
 		Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this
 		SharedPtr<Peer> toPeer(RR->topology->getPeer(toZT));
 
-		if (!network->filterOutgoingPacket(RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId)) {
+		if (!network->filterOutgoingPacket(false,RR->identity.address(),toZT,from,to,(const uint8_t *)data,len,etherType,vlanId)) {
 			TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
 			return;
 		}
@@ -487,13 +487,17 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 		}
 
 		//TRACE("%.16llx: UNICAST: %s -> %s etherType==%s(%.4x) vlanId==%u len==%u fromBridged==%d includeCom==%d",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),etherType,vlanId,len,(int)fromBridged,(int)includeCom);
-
-		return;
-	}
-
-	{
+	} else {
 		// Destination is bridged behind a remote peer
 
+		// We filter with a NULL destination ZeroTier address first. Filtrations
+		// for each ZT destination are also done below. This is the same rationale
+		// and design as for multicast.
+		if (!network->filterOutgoingPacket(false,RR->identity.address(),Address(),from,to,(const uint8_t *)data,len,etherType,vlanId)) {
+			TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
+			return;
+		}
+
 		Address bridges[ZT_MAX_BRIDGE_SPAM];
 		unsigned int numBridges = 0;
 
@@ -527,16 +531,19 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 		}
 
 		for(unsigned int b=0;b<numBridges;++b) {
-			SharedPtr<Peer> bridgePeer(RR->topology->getPeer(bridges[b]));
-			Packet outp(bridges[b],RR->identity.address(),Packet::VERB_EXT_FRAME);
-			outp.append(network->id());
-			outp.append((uint8_t)0x00);
-			to.appendTo(outp);
-			from.appendTo(outp);
-			outp.append((uint16_t)etherType);
-			outp.append(data,len);
-			outp.compress();
-			send(outp,true);
+			if (network->filterOutgoingPacket(true,RR->identity.address(),bridges[b],from,to,(const uint8_t *)data,len,etherType,vlanId)) {
+				Packet outp(bridges[b],RR->identity.address(),Packet::VERB_EXT_FRAME);
+				outp.append(network->id());
+				outp.append((uint8_t)0x00);
+				to.appendTo(outp);
+				from.appendTo(outp);
+				outp.append((uint16_t)etherType);
+				outp.append(data,len);
+				outp.compress();
+				send(outp,true);
+			} else {
+				TRACE("%.16llx: %s -> %s %s packet not sent: filterOutgoingPacket() returned false",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType));
+			}
 		}
 	}
 }

+ 3 - 1
one.cpp

@@ -403,7 +403,9 @@ static int cli(int argc,char **argv)
 								}
 							}
 							if (aa.length() == 0) aa = "-";
-							out << "200 listnetworks " << n["nwid"].get<std::string>() << " " << n["name"].get<std::string>() << " " << n["mac"].get<std::string>() << " " << n["status"].get<std::string>() << " " << n["type"].get<std::string>() << " " << n["portDeviceName"].get<std::string>() << " " << aa << ZT_EOL_S;
+							std::string name = n["name"];
+							if (name.length() == 0) name = "-";
+							out << "200 listnetworks " << n["nwid"].get<std::string>() << " " << name << " " << n["mac"].get<std::string>() << " " << n["status"].get<std::string>() << " " << n["type"].get<std::string>() << " " << n["portDeviceName"].get<std::string>() << " " << aa << ZT_EOL_S;
 						}
 					}
 				}