diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/IncomingPacket.cpp | 10 | ||||
-rw-r--r-- | node/InetAddress.cpp | 24 | ||||
-rw-r--r-- | node/InetAddress.hpp | 8 | ||||
-rw-r--r-- | node/Node.cpp | 26 | ||||
-rw-r--r-- | node/Node.hpp | 9 | ||||
-rw-r--r-- | node/Peer.cpp | 2 |
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; |