Browse Source

Remove somewhat ugly and costly anti-recursion hack -- we will switch to more explicit methods.

Adam Ierymenko 9 years ago
parent
commit
1023ef23b7
7 changed files with 0 additions and 175 deletions
  1. 0 135
      node/AntiRecursion.hpp
  2. 0 15
      node/IncomingPacket.cpp
  3. 0 4
      node/Node.cpp
  4. 0 2
      node/Path.cpp
  5. 0 5
      node/Peer.cpp
  6. 0 3
      node/RuntimeEnvironment.hpp
  7. 0 11
      node/Switch.cpp

+ 0 - 135
node/AntiRecursion.hpp

@@ -1,135 +0,0 @@
-/*
- * ZeroTier One - Network Virtualization Everywhere
- * Copyright (C) 2011-2015  ZeroTier, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * ZeroTier may be used and distributed under the terms of the GPLv3, which
- * are available at: http://www.gnu.org/licenses/gpl-3.0.html
- *
- * If you would like to embed ZeroTier into a commercial application or
- * redistribute it in a modified binary form, please contact ZeroTier Networks
- * LLC. Start here: http://www.zerotier.com/
- */
-
-#ifndef ZT_ANTIRECURSION_HPP
-#define ZT_ANTIRECURSION_HPP
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "Constants.hpp"
-
-namespace ZeroTier {
-
-/**
- * Size of anti-recursion history
- */
-#define ZT_ANTIRECURSION_HISTORY_SIZE 16
-
-/**
- * Filter to prevent recursion (ZeroTier-over-ZeroTier)
- *
- * This works by logging ZeroTier packets that we send. It's then invoked
- * again against packets read from local Ethernet taps. If the last 32
- * bytes representing the ZeroTier packet match in the tap frame, then
- * the frame is a re-injection of a frame that we sent and is rejected.
- *
- * This means that ZeroTier packets simply will not traverse ZeroTier
- * networks, which would cause all sorts of weird problems.
- *
- * This is highly optimized code since it's checked for every packet.
- */
-class AntiRecursion
-{
-public:
-	AntiRecursion()
-	{
-		for(int i=0;i<ZT_ANTIRECURSION_HISTORY_SIZE;++i) {
-			_history[i].tail[0] = 0;
-			_history[i].tail[1] = 0;
-			_history[i].tail[2] = 0;
-			_history[i].tail[3] = 0;
-		}
-		_ptr = 0;
-	}
-
-	/**
-	 * Add an outgoing ZeroTier packet to the circular log
-	 *
-	 * @param data ZT packet data
-	 * @param len Length of packet
-	 */
-	inline void logOutgoingZT(const void *const data,const unsigned int len)
-	{
-		if (len < 32)
-			return;
-#ifdef ZT_NO_TYPE_PUNNING
-		memcpy(_history[++_ptr % ZT_ANTIRECURSION_HISTORY_SIZE].tail,reinterpret_cast<const uint8_t *>(data) + (len - 32),32);
-#else
-		uint64_t *t = _history[++_ptr % ZT_ANTIRECURSION_HISTORY_SIZE].tail;
-		const uint64_t *p = reinterpret_cast<const uint64_t *>(reinterpret_cast<const uint8_t *>(data) + (len - 32));
-		*(t++) = *(p++);
-		*(t++) = *(p++);
-		*(t++) = *(p++);
-		*t = *p;
-#endif
-	}
-
-	/**
-	 * Check an ethernet frame from a local tap against anti-recursion history
-	 *
-	 * @param data Raw frame data
-	 * @param len Length of frame
-	 * @return True if frame is OK to be passed, false if it's a ZT frame that we sent
-	 */
-	inline bool checkEthernetFrame(const void *const data,const unsigned int len) const
-	{
-		if (len < 32)
-			return true;
-		const uint8_t *const pp = reinterpret_cast<const uint8_t *>(data) + (len - 32);
-		const _ArItem *i = _history;
-		const _ArItem *const end = i + ZT_ANTIRECURSION_HISTORY_SIZE;
-		while (i != end) {
-#ifdef ZT_NO_TYPE_PUNNING
-			if (!memcmp(pp,i->tail,32)) {
-				return false;
-			}
-#else
-			const uint64_t *t = i->tail;
-			const uint64_t *p = reinterpret_cast<const uint64_t *>(pp);
-			uint64_t bits = *(t++) ^ *(p++);
-			bits |= *(t++) ^ *(p++);
-			bits |= *(t++) ^ *(p++);
-			bits |= *t ^ *p;
-			if (!bits) {
-				return false;
-			}
-#endif
-			++i;
-		}
-		return true;
-	}
-
-private:
-	struct _ArItem { uint64_t tail[4]; };
-	_ArItem _history[ZT_ANTIRECURSION_HISTORY_SIZE];
-	volatile unsigned long _ptr;
-};
-
-} // namespace ZeroTier
-
-#endif

+ 0 - 15
node/IncomingPacket.cpp

@@ -45,7 +45,6 @@
 #include "World.hpp"
 #include "Cluster.hpp"
 #include "Node.hpp"
-#include "AntiRecursion.hpp"
 #include "DeferredPackets.hpp"
 
 namespace ZeroTier {
@@ -163,7 +162,6 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer>
 						Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
 						nconf->com().serialize(outp);
 						outp.armor(peer->key(),true);
-						RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 						RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 					}
 				}
@@ -250,7 +248,6 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,SharedPtr<Peer> &peer
 							outp.append((uint64_t)pid);
 							outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION);
 							outp.armor(key,true);
-							RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 							RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 						} else {
 							TRACE("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_remoteAddress.toString().c_str());
@@ -346,7 +343,6 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,SharedPtr<Peer> &peer
 		}
 
 		outp.armor(peer->key(),true);
-		RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 		RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 
 		peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); // important for this to go first so received() knows the version
@@ -484,7 +480,6 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer>
 				outp.append(packetId());
 				queried.serialize(outp,false);
 				outp.armor(peer->key(),true);
-				RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 				RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 			} else {
 #ifdef ZT_ENABLE_CLUSTER
@@ -645,7 +640,6 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,const SharedPtr<Peer>
 		if (size() > ZT_PACKET_IDX_PAYLOAD)
 			outp.append(reinterpret_cast<const unsigned char *>(data()) + ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD);
 		outp.armor(peer->key(),true);
-		RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 		RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 		peer->received(_localAddress,_remoteAddress,hops(),pid,Packet::VERB_ECHO,0,Packet::VERB_NOP);
 	} catch ( ... ) {
@@ -723,7 +717,6 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
 						if (outp.size() > ZT_PROTO_MAX_PACKET_LENGTH) { // sanity check
 							TRACE("NETWORK_CONFIG_REQUEST failed: internal error: netconf size %u is too large",(unsigned int)netconfStr.length());
 						} else {
-							RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 							RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 						}
 					}
@@ -736,7 +729,6 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
 					outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
 					outp.append(nwid);
 					outp.armor(peer->key(),true);
-					RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 					RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 				}	break;
 
@@ -747,7 +739,6 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
 					outp.append((unsigned char)Packet::ERROR_NETWORK_ACCESS_DENIED_);
 					outp.append(nwid);
 					outp.armor(peer->key(),true);
-					RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 					RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 				} break;
 
@@ -770,7 +761,6 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
 			outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION);
 			outp.append(nwid);
 			outp.armor(peer->key(),true);
-			RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 			RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 		}
 	} catch ( ... ) {
@@ -816,7 +806,6 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar
 			const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit);
 			if (gatheredLocally) {
 				outp.armor(peer->key(),true);
-				RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 				RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 			}
 
@@ -910,7 +899,6 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share
 				outp.append((unsigned char)0x02); // flag 0x02 = contains gather results
 				if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) {
 					outp.armor(peer->key(),true);
-					RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 					RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 				}
 			}
@@ -1221,7 +1209,6 @@ bool IncomingPacket::_doREQUEST_PROOF_OF_WORK(const RuntimeEnvironment *RR,const
 						outp.append((uint16_t)sizeof(result));
 						outp.append(result,sizeof(result));
 						outp.armor(peer->key(),true);
-						RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 						RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 					} else {
 						Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
@@ -1229,7 +1216,6 @@ bool IncomingPacket::_doREQUEST_PROOF_OF_WORK(const RuntimeEnvironment *RR,const
 						outp.append(pid);
 						outp.append((unsigned char)Packet::ERROR_INVALID_REQUEST);
 						outp.armor(peer->key(),true);
-						RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 						RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 					}
 				}	break;
@@ -1335,7 +1321,6 @@ void IncomingPacket::_sendErrorNeedCertificate(const RuntimeEnvironment *RR,cons
 	outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
 	outp.append(nwid);
 	outp.armor(peer->key(),true);
-	RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 	RR->node->putPacket(_localAddress,_remoteAddress,outp.data(),outp.size());
 }
 

+ 0 - 4
node/Node.cpp

@@ -39,7 +39,6 @@
 #include "NetworkController.hpp"
 #include "Switch.hpp"
 #include "Multicaster.hpp"
-#include "AntiRecursion.hpp"
 #include "Topology.hpp"
 #include "Buffer.hpp"
 #include "Packet.hpp"
@@ -114,7 +113,6 @@ Node::Node(
 	try {
 		RR->sw = new Switch(RR);
 		RR->mc = new Multicaster(RR);
-		RR->antiRec = new AntiRecursion();
 		RR->topology = new Topology(RR);
 		RR->sa = new SelfAwareness(RR);
 		RR->dp = new DeferredPackets(RR);
@@ -122,7 +120,6 @@ Node::Node(
 		delete RR->dp;
 		delete RR->sa;
 		delete RR->topology;
-		delete RR->antiRec;
 		delete RR->mc;
 		delete RR->sw;
 		throw;
@@ -141,7 +138,6 @@ Node::~Node()
 	delete RR->dp;
 	delete RR->sa;
 	delete RR->topology;
-	delete RR->antiRec;
 	delete RR->mc;
 	delete RR->sw;
 #ifdef ZT_ENABLE_CLUSTER

+ 0 - 2
node/Path.cpp

@@ -26,7 +26,6 @@
  */
 
 #include "Path.hpp"
-#include "AntiRecursion.hpp"
 #include "RuntimeEnvironment.hpp"
 #include "Node.hpp"
 
@@ -34,7 +33,6 @@ namespace ZeroTier {
 
 bool Path::send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now)
 {
-	RR->antiRec->logOutgoingZT(data,len);
 	if (RR->node->putPacket(_localAddress,address(),data,len)) {
 		sent(now);
 		return true;

+ 0 - 5
node/Peer.cpp

@@ -32,7 +32,6 @@
 #include "Node.hpp"
 #include "Switch.hpp"
 #include "Network.hpp"
-#include "AntiRecursion.hpp"
 #include "SelfAwareness.hpp"
 #include "Cluster.hpp"
 #include "Packet.hpp"
@@ -104,7 +103,6 @@ void Peer::received(
 				}
 				outp.append((uint16_t)redirectTo.port());
 				outp.armor(_key,true);
-				RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 				RR->node->putPacket(localAddr,remoteAddr,outp.data(),outp.size());
 			} else {
 				// For older peers we use RENDEZVOUS to coax them into contacting us elsewhere.
@@ -120,7 +118,6 @@ void Peer::received(
 					outp.append(redirectTo.rawIpData(),16);
 				}
 				outp.armor(_key,true);
-				RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 				RR->node->putPacket(localAddr,remoteAddr,outp.data(),outp.size());
 			}
 			suboptimalPath = true;
@@ -199,7 +196,6 @@ void Peer::received(
 						// 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->antiRec->logOutgoingZT(outp.data(),outp.size());
 						RR->node->putPacket(localAddr,remoteAddr,outp.data(),outp.size());
 					} else {
 						sendHELLO(localAddr,remoteAddr,now);
@@ -233,7 +229,6 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u
 	outp.append((uint64_t)RR->topology->worldTimestamp());
 
 	outp.armor(_key,false); // HELLO is sent in the clear
-	RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 	RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size(),ttl);
 }
 

+ 0 - 3
node/RuntimeEnvironment.hpp

@@ -41,7 +41,6 @@ class Switch;
 class Topology;
 class Node;
 class Multicaster;
-class AntiRecursion;
 class NetworkController;
 class SelfAwareness;
 class Cluster;
@@ -59,7 +58,6 @@ public:
 		,localNetworkController((NetworkController *)0)
 		,sw((Switch *)0)
 		,mc((Multicaster *)0)
-		,antiRec((AntiRecursion *)0)
 		,topology((Topology *)0)
 		,sa((SelfAwareness *)0)
 		,dp((DeferredPackets *)0)
@@ -91,7 +89,6 @@ public:
 
 	Switch *sw;
 	Multicaster *mc;
-	AntiRecursion *antiRec;
 	Topology *topology;
 	SelfAwareness *sa;
 	DeferredPackets *dp;

+ 0 - 11
node/Switch.cpp

@@ -42,7 +42,6 @@
 #include "InetAddress.hpp"
 #include "Topology.hpp"
 #include "Peer.hpp"
-#include "AntiRecursion.hpp"
 #include "SelfAwareness.hpp"
 #include "Packet.hpp"
 #include "Cluster.hpp"
@@ -97,7 +96,6 @@ void Switch::onRemotePacket(const InetAddress &localAddr,const InetAddress &from
 					_lastBeaconResponse = now;
 					Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP);
 					outp.armor(peer->key(),true);
-					RR->antiRec->logOutgoingZT(outp.data(),outp.size());
 					RR->node->putPacket(localAddr,fromAddr,outp.data(),outp.size());
 				}
 			}
@@ -125,15 +123,6 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
 	if (to == network->mac())
 		return;
 
-	/* Check anti-recursion module to ensure that this is not ZeroTier talking over its own links.
-	 * Note: even when we introduce a more purposeful binding of the main UDP port, this can
-	 * still happen because Windows likes to send broadcasts over interfaces that have little
-	 * to do with their intended target audience. :P */
-	if (!RR->antiRec->checkEthernetFrame(data,len)) {
-		TRACE("%.16llx: rejected recursively addressed ZeroTier packet by tail match (type %s, length: %u)",network->id(),etherTypeName(etherType),len);
-		return;
-	}
-
 	// Check to make sure this protocol is allowed on this network
 	if (!nconf->permitsEtherType(etherType)) {
 		TRACE("%.16llx: ignored tap: %s -> %s: ethertype %s not allowed on network %.16llx",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),(unsigned long long)network->id());