summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2016-01-11 10:17:44 -0800
committerAdam Ierymenko <adam.ierymenko@gmail.com>2016-01-11 10:17:44 -0800
commitb3e3d4cacca37a4850e4e1a91fb8c42a5b13cb26 (patch)
tree0fbeba94f3021f8d55ada20c5ed8d193f574d70f /node
parentba2a89c760f9bfa4936f3cf89155aafd047af917 (diff)
downloadinfinitytier-b3e3d4cacca37a4850e4e1a91fb8c42a5b13cb26.tar.gz
infinitytier-b3e3d4cacca37a4850e4e1a91fb8c42a5b13cb26.zip
Instead of using binary packet comparison, add a callback to the API to explicitly check whether paths should be used. Check in with this callback (if present) when learning new paths or sending initial packets.
Diffstat (limited to 'node')
-rw-r--r--node/IncomingPacket.cpp10
-rw-r--r--node/InetAddress.cpp24
-rw-r--r--node/InetAddress.hpp8
-rw-r--r--node/Node.cpp26
-rw-r--r--node/Node.hpp9
-rw-r--r--node/Peer.cpp2
6 files changed, 73 insertions, 6 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index 5c9279dd..c63d70b7 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -507,10 +507,12 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<
const unsigned int port = at<uint16_t>(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT);
const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN];
if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) {
+ peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP);
+
InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
- peer->received(_localAddress,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP);
- RR->sw->rendezvous(withPeer,_localAddress,atAddr);
+ if (RR->node->shouldUsePathForZeroTierTraffic(_localAddress,atAddr))
+ RR->sw->rendezvous(withPeer,_localAddress,atAddr);
} else {
TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
}
@@ -941,7 +943,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
switch(addrType) {
case 4: {
InetAddress a(field(ptr,4),4,at<uint16_t>(ptr + 4));
- if ( ((flags & 0x01) == 0) && (Path::isAddressValidForPath(a)) && (!peer->hasActivePathTo(now,a)) ) {
+ if ( ((flags & 0x01) == 0) && (Path::isAddressValidForPath(a)) && (!peer->hasActivePathTo(now,a)) && (RR->node->shouldUsePathForZeroTierTraffic(_localAddress,a)) ) {
if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
peer->sendHELLO(_localAddress,a,now);
@@ -952,7 +954,7 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha
} break;
case 6: {
InetAddress a(field(ptr,16),16,at<uint16_t>(ptr + 16));
- if ( ((flags & 0x01) == 0) && (Path::isAddressValidForPath(a)) && (!peer->hasActivePathTo(now,a)) ) {
+ if ( ((flags & 0x01) == 0) && (Path::isAddressValidForPath(a)) && (!peer->hasActivePathTo(now,a)) && (RR->node->shouldUsePathForZeroTierTraffic(_localAddress,a)) ) {
if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
peer->sendHELLO(_localAddress,a,now);
diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp
index f35eb9c3..1b3a8064 100644
--- a/node/InetAddress.cpp
+++ b/node/InetAddress.cpp
@@ -280,6 +280,30 @@ InetAddress InetAddress::network() const
return r;
}
+bool InetAddress::containsAddress(const InetAddress &addr) const
+{
+ if (addr.ss_family == ss_family) {
+ switch(ss_family) {
+ case AF_INET: {
+ const unsigned int bits = netmaskBits();
+ return ( (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(&addr)->sin_addr.s_addr) >> (32 - bits)) == (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) >> (32 - bits)) );
+ }
+ case AF_INET6: {
+ const InetAddress mask(netmask());
+ const uint8_t *m = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&mask)->sin6_addr.s6_addr);
+ const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_addr.s6_addr);
+ const uint8_t *b = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
+ for(unsigned int i=0;i<16;++i) {
+ if ((a[i] & m[i]) != b[i])
+ return false;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
bool InetAddress::isNetwork() const
throw()
{
diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp
index 2573e694..201271f7 100644
--- a/node/InetAddress.hpp
+++ b/node/InetAddress.hpp
@@ -326,6 +326,14 @@ struct InetAddress : public sockaddr_storage
InetAddress network() const;
/**
+ * Test whether this IP/netmask contains this address
+ *
+ * @param addr Address to check
+ * @return True if this IP/netmask (route) contains this address
+ */
+ bool containsAddress(const InetAddress &addr) const;
+
+ /**
* @return True if this is an IPv4 address
*/
inline bool isV4() const throw() { return (ss_family == AF_INET); }
diff --git a/node/Node.cpp b/node/Node.cpp
index 19675bb5..f65aa843 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -64,6 +64,7 @@ Node::Node(
ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
+ ZT_PathCheckFunction pathCheckFunction,
ZT_EventCallback eventCallback) :
_RR(this),
RR(&_RR),
@@ -73,6 +74,7 @@ Node::Node(
_wirePacketSendFunction(wirePacketSendFunction),
_virtualNetworkFrameFunction(virtualNetworkFrameFunction),
_virtualNetworkConfigFunction(virtualNetworkConfigFunction),
+ _pathCheckFunction(pathCheckFunction),
_eventCallback(eventCallback),
_networks(),
_networks_m(),
@@ -671,6 +673,27 @@ std::string Node::dataStoreGet(const char *name)
return r;
}
+bool Node::shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const InetAddress &remoteAddress)
+{
+ {
+ Mutex::Lock _l(_networks_m);
+ for(std::vector< std::pair< uint64_t, SharedPtr<Network> > >::const_iterator i=_networks.begin();i!=_networks.end();++i) {
+ SharedPtr<NetworkConfig> nc(i->second->config2());
+ if (nc) {
+ for(std::vector<InetAddress>::const_iterator a(nc->staticIps().begin());a!=nc->staticIps().end();++a) {
+ if (a->containsAddress(remoteAddress)) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ if (_pathCheckFunction)
+ return (_pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,reinterpret_cast<const struct sockaddr_storage *>(&localAddress),reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0);
+ else return true;
+}
+
#ifdef ZT_TRACE
void Node::postTrace(const char *module,unsigned int line,const char *fmt,...)
{
@@ -743,11 +766,12 @@ enum ZT_ResultCode ZT_Node_new(
ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
+ ZT_PathCheckFunction pathCheckFunction,
ZT_EventCallback eventCallback)
{
*node = (ZT_Node *)0;
try {
- *node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(now,uptr,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,eventCallback));
+ *node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(now,uptr,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,pathCheckFunction,eventCallback));
return ZT_RESULT_OK;
} catch (std::bad_alloc &exc) {
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
diff --git a/node/Node.hpp b/node/Node.hpp
index 15295139..b6b32363 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -71,6 +71,7 @@ public:
ZT_WirePacketSendFunction wirePacketSendFunction,
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
+ ZT_PathCheckFunction pathCheckFunction,
ZT_EventCallback eventCallback);
~Node();
@@ -189,6 +190,13 @@ public:
len);
}
+ /**
+ * @param localAddress Local address
+ * @param remoteAddress Remote address
+ * @return True if path should be used
+ */
+ bool shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const InetAddress &remoteAddress);
+
inline SharedPtr<Network> network(uint64_t nwid) const
{
Mutex::Lock _l(_networks_m);
@@ -288,6 +296,7 @@ private:
ZT_WirePacketSendFunction _wirePacketSendFunction;
ZT_VirtualNetworkFrameFunction _virtualNetworkFrameFunction;
ZT_VirtualNetworkConfigFunction _virtualNetworkConfigFunction;
+ ZT_PathCheckFunction _pathCheckFunction;
ZT_EventCallback _eventCallback;
std::vector< std::pair< uint64_t, SharedPtr<Network> > > _networks;
diff --git a/node/Peer.cpp b/node/Peer.cpp
index 04e5bdf0..c75a3e46 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -156,7 +156,7 @@ void Peer::received(
}
}
- if (!pathIsConfirmed) {
+ if ((!pathIsConfirmed)&&(RR->node->shouldUsePathForZeroTierTraffic(localAddr,remoteAddr))) {
if (verb == Packet::VERB_OK) {
Path *slot = (Path *)0;