diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-09-24 11:00:22 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-09-24 11:00:22 -0700 |
commit | fbde40d1fc8767e4b6e9fcf0b078a8a4eb0646bd (patch) | |
tree | e6776e96db9f90e985ac86c9967d7d945033328a /node | |
parent | 557c0c29b0781ff6190189fc080075b1c773f382 (diff) | |
parent | 0e5aac6a117c28fde63f4cdb94e6c9fc415ca098 (diff) | |
download | infinitytier-fbde40d1fc8767e4b6e9fcf0b078a8a4eb0646bd.tar.gz infinitytier-fbde40d1fc8767e4b6e9fcf0b078a8a4eb0646bd.zip |
Merge branch 'adamierymenko-dev' into netcon
Diffstat (limited to 'node')
-rw-r--r-- | node/Hashtable.hpp | 2 | ||||
-rw-r--r-- | node/IncomingPacket.cpp | 58 | ||||
-rw-r--r-- | node/IncomingPacket.hpp | 5 | ||||
-rw-r--r-- | node/Node.cpp | 16 | ||||
-rw-r--r-- | node/Node.hpp | 5 | ||||
-rw-r--r-- | node/Path.hpp | 11 | ||||
-rw-r--r-- | node/Peer.cpp | 25 | ||||
-rw-r--r-- | node/Peer.hpp | 5 | ||||
-rw-r--r-- | node/RemotePath.hpp | 9 | ||||
-rw-r--r-- | node/SHA512.cpp | 12 | ||||
-rw-r--r-- | node/Switch.cpp | 27 | ||||
-rw-r--r-- | node/Switch.hpp | 14 | ||||
-rw-r--r-- | node/Topology.cpp | 2 |
13 files changed, 118 insertions, 73 deletions
diff --git a/node/Hashtable.hpp b/node/Hashtable.hpp index d2b85c15..beef1468 100644 --- a/node/Hashtable.hpp +++ b/node/Hashtable.hpp @@ -383,7 +383,7 @@ private: static inline unsigned long _hc(const uint32_t i) { // In the uint32_t case we use a simple multiplier for hashing to ensure coverage - return ((unsigned long)i * (unsigned long)2654435761); + return ((unsigned long)i * (unsigned long)0x9e3779b1); } inline void _grow() diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index fc79270b..e4861af7 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -69,7 +69,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR) switch(verb()) { //case Packet::VERB_NOP: default: // ignore unknown verbs, but if they pass auth check they are "received" - peer->received(RR,_remoteAddress,hops(),packetId(),verb(),0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),verb(),0,Packet::VERB_NOP); return true; case Packet::VERB_HELLO: return _doHELLO(RR); case Packet::VERB_ERROR: return _doERROR(RR,peer); @@ -144,7 +144,7 @@ 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->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } } } break; @@ -165,7 +165,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> default: break; } - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb); } catch (std::exception &ex) { TRACE("dropped ERROR from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -231,7 +231,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) outp.append(packetId()); outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION); outp.armor(key,true); - RR->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } else { RR->node->postEvent(ZT1_EVENT_AUTHENTICATION_FAILURE,(const void *)&_remoteAddress); TRACE("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_remoteAddress.toString().c_str()); @@ -278,7 +278,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) // VALID -- continues here - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP); peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); bool trusted = false; @@ -316,7 +316,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) } outp.armor(peer->key(),true); - RR->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } catch (std::exception &ex) { TRACE("dropped HELLO from %s(%s): %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -436,7 +436,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p default: break; } - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb); } catch (std::exception &ex) { TRACE("dropped OK from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -456,7 +456,7 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer> outp.append(packetId()); queried->identity().serialize(outp,false); outp.armor(peer->key(),true); - RR->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } else { Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR); outp.append((unsigned char)Packet::VERB_WHOIS); @@ -464,12 +464,12 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer> outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND); outp.append(payload(),ZT_ADDRESS_LENGTH); outp.armor(peer->key(),true); - RR->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } } else { TRACE("dropped WHOIS from %s(%s): missing or invalid address",source().toString().c_str(),_remoteAddress.toString().c_str()); } - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP); } catch ( ... ) { TRACE("dropped WHOIS from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str()); } @@ -487,8 +487,8 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr< if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) { 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(RR,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP); - RR->sw->rendezvous(withPeer,atAddr); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP); + RR->sw->rendezvous(withPeer,_localInterfaceId,atAddr); } else { TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",peer->address().toString().c_str(),_remoteAddress.toString().c_str()); } @@ -525,7 +525,7 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> RR->node->putFrame(network->id(),MAC(peer->address(),network->id()),network->mac(),etherType,0,field(ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,payloadLen),payloadLen); } - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP); } else { TRACE("dropped FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)); } @@ -602,7 +602,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P RR->node->putFrame(network->id(),from,to,etherType,0,field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD,payloadLen),payloadLen); } - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP); } else { TRACE("dropped EXT_FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)); } @@ -623,7 +623,7 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const Shared for(unsigned int ptr=ZT_PACKET_IDX_PAYLOAD;ptr<size();ptr+=18) RR->mc->add(now,at<uint64_t>(ptr),MulticastGroup(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14)),peer->address()); - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP); } catch (std::exception &ex) { TRACE("dropped MULTICAST_LIKE from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -647,7 +647,7 @@ bool IncomingPacket::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment } } - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE,0,Packet::VERB_NOP); } catch (std::exception &ex) { TRACE("dropped NETWORK_MEMBERSHIP_CERTIFICATE from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -666,7 +666,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons const unsigned int h = hops(); const uint64_t pid = packetId(); - peer->received(RR,_remoteAddress,h,pid,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,h,pid,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP); if (RR->localNetworkController) { Dictionary netconf; @@ -688,7 +688,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons if (outp.size() > ZT_PROTO_MAX_PACKET_LENGTH) { TRACE("NETWORK_CONFIG_REQUEST failed: internal error: netconf size %u is too large",(unsigned int)netconfStr.length()); } else { - RR->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } } } break; @@ -700,7 +700,7 @@ 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->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } break; case NetworkController::NETCONF_QUERY_ACCESS_DENIED: { @@ -710,7 +710,7 @@ 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->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } break; case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR: @@ -732,7 +732,7 @@ 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->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } } catch (std::exception &exc) { TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); @@ -753,7 +753,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *RR,cons nw->requestConfiguration(); ptr += 8; } - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REFRESH,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REFRESH,0,Packet::VERB_NOP); } catch (std::exception &exc) { TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); } catch ( ... ) { @@ -780,11 +780,11 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar outp.append((uint32_t)mg.adi()); if (RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit)) { outp.armor(peer->key(),true); - RR->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } } - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP); } catch (std::exception &exc) { TRACE("dropped MULTICAST_GATHER from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); } catch ( ... ) { @@ -871,12 +871,12 @@ 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->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } } } // else ignore -- not a member of this network - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP); + peer->received(RR,_localInterfaceId,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP); } catch (std::exception &exc) { TRACE("dropped MULTICAST_FRAME from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); } catch ( ... ) { @@ -905,14 +905,14 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha InetAddress a(field(ptr,4),4,at<uint16_t>(ptr + 4)); if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) ) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); - peer->attemptToContactAt(RR,a,RR->node->now()); + peer->attemptToContactAt(RR,_localInterfaceId,a,RR->node->now()); } } break; case 6: { InetAddress a(field(ptr,16),16,at<uint16_t>(ptr + 16)); if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) ) { TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str()); - peer->attemptToContactAt(RR,a,RR->node->now()); + peer->attemptToContactAt(RR,_localInterfaceId,a,RR->node->now()); } } break; } @@ -934,7 +934,7 @@ 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->node->putPacket(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_localInterfaceId,_remoteAddress,outp.data(),outp.size()); } } // namespace ZeroTier diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index 3bf7737d..170ab7f9 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -72,14 +72,16 @@ public: * * @param data Packet data * @param len Packet length + * @param localInterfaceId Local interface ID * @param remoteAddress Address from which packet came * @param now Current time * @throws std::out_of_range Range error processing packet */ - IncomingPacket(const void *data,unsigned int len,const InetAddress &remoteAddress,uint64_t now) : + IncomingPacket(const void *data,unsigned int len,int localInterfaceId,const InetAddress &remoteAddress,uint64_t now) : Packet(data,len), _receiveTime(now), _remoteAddress(remoteAddress), + _localInterfaceId(localInterfaceId), __refCount() { } @@ -128,6 +130,7 @@ private: uint64_t _receiveTime; InetAddress _remoteAddress; + int _localInterfaceId; AtomicCounter __refCount; }; diff --git a/node/Node.cpp b/node/Node.cpp index c8c50d66..7aad54b8 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -157,13 +157,14 @@ Node::~Node() ZT1_ResultCode Node::processWirePacket( uint64_t now, + int localInterfaceId, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, volatile uint64_t *nextBackgroundTaskDeadline) { _now = now; - RR->sw->onRemotePacket(*(reinterpret_cast<const InetAddress *>(remoteAddress)),packetData,packetLength); + RR->sw->onRemotePacket(localInterfaceId,*(reinterpret_cast<const InetAddress *>(remoteAddress)),packetData,packetLength); return ZT1_RESULT_OK; } @@ -232,7 +233,9 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next _now = now; Mutex::Lock bl(_backgroundTasksLock); - if ((now - _lastPingCheck) >= ZT_PING_CHECK_INVERVAL) { + unsigned long timeUntilNextPingCheck = ZT_PING_CHECK_INVERVAL; + const uint64_t timeSinceLastPingCheck = now - _lastPingCheck; + if (timeSinceLastPingCheck >= ZT_PING_CHECK_INVERVAL) { try { _lastPingCheck = now; @@ -261,7 +264,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next if (nr->second) { SharedPtr<Peer> rp(RR->topology->getPeer(nr->first)); if ((rp)&&(!rp->hasActiveDirectPath(now))) - rp->attemptToContactAt(RR,nr->second,now); + rp->attemptToContactAt(RR,-1,nr->second,now); } } @@ -277,6 +280,8 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next } catch ( ... ) { return ZT1_RESULT_FATAL_ERROR_INTERNAL; } + } else { + timeUntilNextPingCheck -= (unsigned long)timeSinceLastPingCheck; } if ((now - _lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) { @@ -291,7 +296,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next } try { - *nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min((unsigned long)ZT_PING_CHECK_INVERVAL,RR->sw->doTimerTasks(now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY); + *nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY); } catch ( ... ) { return ZT1_RESULT_FATAL_ERROR_INTERNAL; } @@ -569,13 +574,14 @@ void ZT1_Node_delete(ZT1_Node *node) enum ZT1_ResultCode ZT1_Node_processWirePacket( ZT1_Node *node, uint64_t now, + int localInterfaceId, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, volatile uint64_t *nextBackgroundTaskDeadline) { try { - return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(now,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline); + return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(now,localInterfaceId,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline); } catch (std::bad_alloc &exc) { return ZT1_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { diff --git a/node/Node.hpp b/node/Node.hpp index 2a283eab..0e614e5a 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -80,6 +80,7 @@ public: ZT1_ResultCode processWirePacket( uint64_t now, + int localInterfaceId, const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, @@ -119,16 +120,18 @@ public: /** * Enqueue a ZeroTier message to be sent * + * @param localInterfaceId Local interface ID, -1 for unspecified/random * @param addr Destination address * @param data Packet data * @param len Packet length * @return True if packet appears to have been sent */ - inline bool putPacket(const InetAddress &addr,const void *data,unsigned int len) + inline bool putPacket(int localInterfaceId,const InetAddress &addr,const void *data,unsigned int len) { return (_wirePacketSendFunction( reinterpret_cast<ZT1_Node *>(this), _uPtr, + localInterfaceId, reinterpret_cast<const struct sockaddr_storage *>(&addr), data, len) == 0); diff --git a/node/Path.hpp b/node/Path.hpp index 0e53772d..1f947911 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -93,7 +93,16 @@ public: /** * @return Preference rank, higher == better */ - inline int preferenceRank() const throw() { return (int)_ipScope; } // IP scopes are in ascending rank order in InetAddress.hpp + inline int preferenceRank() const throw() + { + // First, since the scope enum values in InetAddress.hpp are in order of + // use preference rank, we take that. Then we multiple by two, yielding + // a sequence like 0, 2, 4, 6, etc. Then if it's IPv6 we add one. This + // makes IPv6 addresses of a given scope outrank IPv4 addresses of the + // same scope -- e.g. 1 outranks 0. This makes us prefer IPv6, but not + // if the address scope/class is of a fundamentally lower rank. + return ( ((int)_ipScope * 2) + ((_addr.ss_family == AF_INET6) ? 1 : 0) ); + } /** * @return Path trust level diff --git a/node/Peer.cpp b/node/Peer.cpp index c27afa8f..e966a9bf 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -39,6 +39,9 @@ namespace ZeroTier { +// Used to send varying values for NAT keepalive +static uint32_t _natKeepaliveBuf = 0; + Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity) throw(std::runtime_error) : _lastUsed(0), @@ -61,6 +64,7 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity) void Peer::received( const RuntimeEnvironment *RR, + int localInterfaceId, const InetAddress &remoteAddr, unsigned int hops, uint64_t packetId, @@ -78,7 +82,7 @@ void Peer::received( { unsigned int np = _numPaths; for(unsigned int p=0;p<np;++p) { - if (_paths[p].address() == remoteAddr) { + if ((_paths[p].address() == remoteAddr)&&(_paths[p].localInterfaceId() == localInterfaceId)) { _paths[p].received(now); pathIsConfirmed = true; break; @@ -103,7 +107,7 @@ void Peer::received( } } if (slot) { - *slot = RemotePath(remoteAddr,false); + *slot = RemotePath(localInterfaceId,remoteAddr,false); slot->received(now); _numPaths = np; pathIsConfirmed = true; @@ -116,7 +120,7 @@ void Peer::received( if ((now - _lastPathConfirmationSent) >= ZT_MIN_PATH_CONFIRMATION_INTERVAL) { _lastPathConfirmationSent = now; TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),remoteAddr.toString().c_str()); - attemptToContactAt(RR,remoteAddr,now); + attemptToContactAt(RR,localInterfaceId,remoteAddr,now); } } } @@ -138,7 +142,7 @@ void Peer::received( for(std::vector<MulticastGroup>::const_iterator mg(mgs.begin());mg!=mgs.end();++mg) { if ((outp.size() + 18) > ZT_UDP_DEFAULT_PAYLOAD_MTU) { outp.armor(_key,true); - RR->node->putPacket(remoteAddr,outp.data(),outp.size()); + RR->node->putPacket(localInterfaceId,remoteAddr,outp.data(),outp.size()); outp.reset(_id.address(),RR->identity.address(),Packet::VERB_MULTICAST_LIKE); } @@ -151,7 +155,7 @@ void Peer::received( } if (outp.size() > ZT_PROTO_MIN_PACKET_LENGTH) { outp.armor(_key,true); - RR->node->putPacket(remoteAddr,outp.data(),outp.size()); + RR->node->putPacket(localInterfaceId,remoteAddr,outp.data(),outp.size()); } } } @@ -177,7 +181,7 @@ RemotePath *Peer::getBestPath(uint64_t now) return bestPath; } -void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &atAddress,uint64_t now) +void Peer::attemptToContactAt(const RuntimeEnvironment *RR,int localInterfaceId,const InetAddress &atAddress,uint64_t now) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO); outp.append((unsigned char)ZT_PROTO_VERSION); @@ -205,7 +209,7 @@ void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &at } outp.armor(_key,false); // HELLO is sent in the clear - RR->node->putPacket(atAddress,outp.data(),outp.size()); + RR->node->putPacket(localInterfaceId,atAddress,outp.data(),outp.size()); } void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) @@ -214,11 +218,12 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) if (bestPath) { if ((now - bestPath->lastReceived()) >= ZT_PEER_DIRECT_PING_DELAY) { TRACE("PING %s(%s)",_id.address().toString().c_str(),bestPath->address().toString().c_str()); - attemptToContactAt(RR,bestPath->address(),now); + attemptToContactAt(RR,bestPath->localInterfaceId(),bestPath->address(),now); bestPath->sent(now); } else if (((now - bestPath->lastSend()) >= ZT_NAT_KEEPALIVE_DELAY)&&(!bestPath->reliable())) { + _natKeepaliveBuf += (uint32_t)((now * 0x9e3779b1) >> 1); // tumble this around to send constantly varying (meaningless) payloads TRACE("NAT keepalive %s(%s)",_id.address().toString().c_str(),bestPath->address().toString().c_str()); - RR->node->putPacket(bestPath->address(),"",0); + RR->node->putPacket(bestPath->localInterfaceId(),bestPath->address(),&_natKeepaliveBuf,sizeof(_natKeepaliveBuf)); bestPath->sent(now); } } @@ -350,7 +355,7 @@ bool Peer::resetWithinScope(const RuntimeEnvironment *RR,InetAddress::IpScope sc while (x < np) { if (_paths[x].address().ipScope() == scope) { if (_paths[x].fixed()) { - attemptToContactAt(RR,_paths[x].address(),now); + attemptToContactAt(RR,_paths[x].localInterfaceId(),_paths[x].address(),now); _paths[y++] = _paths[x]; // keep fixed paths } } else { diff --git a/node/Peer.hpp b/node/Peer.hpp index ef436cd9..b0f2b4e2 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -105,6 +105,7 @@ public: * and appears to be valid. * * @param RR Runtime environment + * @param localInterfaceId Local interface ID or -1 if unspecified * @param remoteAddr Internet address of sender * @param hops ZeroTier (not IP) hops * @param packetId Packet ID @@ -114,6 +115,7 @@ public: */ void received( const RuntimeEnvironment *RR, + int localInterfaceId, const InetAddress &remoteAddr, unsigned int hops, uint64_t packetId, @@ -155,10 +157,11 @@ public: * for NAT traversal and path verification. * * @param RR Runtime environment + * @param localInterfaceId Local interface ID or -1 for unspecified * @param atAddress Destination address * @param now Current time */ - void attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &atAddress,uint64_t now); + void attemptToContactAt(const RuntimeEnvironment *RR,int localInterfaceId,const InetAddress &atAddress,uint64_t now); /** * Send pings or keepalives depending on configured timeouts diff --git a/node/RemotePath.hpp b/node/RemotePath.hpp index 291943c9..a7ef141b 100644 --- a/node/RemotePath.hpp +++ b/node/RemotePath.hpp @@ -53,14 +53,18 @@ public: Path(), _lastSend(0), _lastReceived(0), + _localInterfaceId(-1), _fixed(false) {} - RemotePath(const InetAddress &addr,bool fixed) : + RemotePath(int localInterfaceId,const InetAddress &addr,bool fixed) : Path(addr,0,TRUST_NORMAL), _lastSend(0), _lastReceived(0), + _localInterfaceId(localInterfaceId), _fixed(fixed) {} + inline int localInterfaceId() const throw() { return _localInterfaceId; } + inline uint64_t lastSend() const throw() { return _lastSend; } inline uint64_t lastReceived() const throw() { return _lastReceived; } @@ -123,7 +127,7 @@ public: */ inline bool send(const RuntimeEnvironment *RR,const void *data,unsigned int len,uint64_t now) { - if (RR->node->putPacket(address(),data,len)) { + if (RR->node->putPacket(_localInterfaceId,address(),data,len)) { sent(now); RR->antiRec->logOutgoingZT(data,len); return true; @@ -134,6 +138,7 @@ public: private: uint64_t _lastSend; uint64_t _lastReceived; + int _localInterfaceId; bool _fixed; }; diff --git a/node/SHA512.cpp b/node/SHA512.cpp index 197d6323..ddff4839 100644 --- a/node/SHA512.cpp +++ b/node/SHA512.cpp @@ -48,10 +48,8 @@ Public domain. #define uint64 uint64_t -#define load_bigendian(x) Utils::ntoh(*((const uint64_t *)(x))) -#define store_bigendian(x,u) (*((uint64_t *)(x)) = Utils::hton((u))) +#ifdef ZT_NO_TYPE_PUNNING -#if 0 static uint64 load_bigendian(const unsigned char *x) { return @@ -77,7 +75,13 @@ static void store_bigendian(unsigned char *x,uint64 u) x[1] = u; u >>= 8; x[0] = u; } -#endif + +#else // !ZT_NO_TYPE_PUNNING + +#define load_bigendian(x) Utils::ntoh(*((const uint64_t *)(x))) +#define store_bigendian(x,u) (*((uint64_t *)(x)) = Utils::hton((u))) + +#endif // ZT_NO_TYPE_PUNNING #define SHR(x,c) ((x) >> (c)) #define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) diff --git a/node/Switch.cpp b/node/Switch.cpp index 995abef4..0de94400 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -78,8 +78,11 @@ Switch::~Switch() { } -void Switch::onRemotePacket(const InetAddress &fromAddr,const void *data,unsigned int len) +void Switch::onRemotePacket(int localInterfaceId,const InetAddress &fromAddr,const void *data,unsigned int len) { + if (localInterfaceId < 0) + localInterfaceId = 0; + try { if (len == 13) { /* LEGACY: before VERB_PUSH_DIRECT_PATHS, peers used broadcast @@ -96,14 +99,14 @@ void Switch::onRemotePacket(const InetAddress &fromAddr,const void *data,unsigne _lastBeaconResponse = now; Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP); outp.armor(peer->key(),false); - RR->node->putPacket(fromAddr,outp.data(),outp.size()); + RR->node->putPacket(localInterfaceId,fromAddr,outp.data(),outp.size()); } } } else if (len > ZT_PROTO_MIN_FRAGMENT_LENGTH) { if (((const unsigned char *)data)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] == ZT_PACKET_FRAGMENT_INDICATOR) { - _handleRemotePacketFragment(fromAddr,data,len); + _handleRemotePacketFragment(localInterfaceId,fromAddr,data,len); } else if (len >= ZT_PROTO_MIN_PACKET_LENGTH) { - _handleRemotePacketHead(fromAddr,data,len); + _handleRemotePacketHead(localInterfaceId,fromAddr,data,len); } } } catch (std::exception &ex) { @@ -376,14 +379,14 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force) return true; } -void Switch::rendezvous(const SharedPtr<Peer> &peer,const InetAddress &atAddr) +void Switch::rendezvous(const SharedPtr<Peer> &peer,int localInterfaceId,const InetAddress &atAddr) { TRACE("sending NAT-t message to %s(%s)",peer->address().toString().c_str(),atAddr.toString().c_str()); const uint64_t now = RR->node->now(); - peer->attemptToContactAt(RR,atAddr,now); + peer->attemptToContactAt(RR,localInterfaceId,atAddr,now); { Mutex::Lock _l(_contactQueue_m); - _contactQueue.push_back(ContactQueueEntry(peer,now + ZT_NAT_T_TACTICAL_ESCALATION_DELAY,atAddr)); + _contactQueue.push_back(ContactQueueEntry(peer,now + ZT_NAT_T_TACTICAL_ESCALATION_DELAY,localInterfaceId,atAddr)); } } @@ -453,14 +456,14 @@ unsigned long Switch::doTimerTasks(uint64_t now) } else { if (qi->strategyIteration == 0) { // First strategy: send packet directly to destination - qi->peer->attemptToContactAt(RR,qi->inaddr,now); + qi->peer->attemptToContactAt(RR,qi->localInterfaceId,qi->inaddr,now); } else if (qi->strategyIteration <= 4) { // Strategies 1-4: try escalating ports for symmetric NATs that remap sequentially InetAddress tmpaddr(qi->inaddr); int p = (int)qi->inaddr.port() + qi->strategyIteration; if (p < 0xffff) { tmpaddr.setPort((unsigned int)p); - qi->peer->attemptToContactAt(RR,tmpaddr,now); + qi->peer->attemptToContactAt(RR,qi->localInterfaceId,tmpaddr,now); } else qi->strategyIteration = 5; } else { // All strategies tried, expire entry @@ -551,7 +554,7 @@ unsigned long Switch::doTimerTasks(uint64_t now) return nextDelay; } -void Switch::_handleRemotePacketFragment(const InetAddress &fromAddr,const void *data,unsigned int len) +void Switch::_handleRemotePacketFragment(int localInterfaceId,const InetAddress &fromAddr,const void *data,unsigned int len) { Packet::Fragment fragment(data,len); Address destination(fragment.destination()); @@ -622,9 +625,9 @@ void Switch::_handleRemotePacketFragment(const InetAddress &fromAddr,const void } } -void Switch::_handleRemotePacketHead(const InetAddress &fromAddr,const void *data,unsigned int len) +void Switch::_handleRemotePacketHead(int localInterfaceId,const InetAddress &fromAddr,const void *data,unsigned int len) { - SharedPtr<IncomingPacket> packet(new IncomingPacket(data,len,fromAddr,RR->node->now())); + SharedPtr<IncomingPacket> packet(new IncomingPacket(data,len,localInterfaceId,fromAddr,RR->node->now())); Address source(packet->source()); Address destination(packet->destination()); diff --git a/node/Switch.hpp b/node/Switch.hpp index 1ad8459c..1954e0cd 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -69,11 +69,12 @@ public: /** * Called when a packet is received from the real network * + * @param localInterfaceId Local interface ID or -1 for unspecified * @param fromAddr Internet IP address of origin * @param data Packet data * @param len Packet length */ - void onRemotePacket(const InetAddress &fromAddr,const void *data,unsigned int len); + void onRemotePacket(int localInterfaceId,const InetAddress &fromAddr,const void *data,unsigned int len); /** * Called when a packet comes from a local Ethernet tap @@ -130,9 +131,10 @@ public: * Attempt NAT traversal to peer at a given physical address * * @param peer Peer to contact + * @param localInterfaceId Local interface ID or -1 if unspecified * @param atAddr Address of peer */ - void rendezvous(const SharedPtr<Peer> &peer,const InetAddress &atAddr); + void rendezvous(const SharedPtr<Peer> &peer,int localInterfaceId,const InetAddress &atAddr); /** * Request WHOIS on a given address @@ -169,8 +171,8 @@ public: unsigned long doTimerTasks(uint64_t now); private: - void _handleRemotePacketFragment(const InetAddress &fromAddr,const void *data,unsigned int len); - void _handleRemotePacketHead(const InetAddress &fromAddr,const void *data,unsigned int len); + void _handleRemotePacketFragment(int localInterfaceId,const InetAddress &fromAddr,const void *data,unsigned int len); + void _handleRemotePacketHead(int localInterfaceId,const InetAddress &fromAddr,const void *data,unsigned int len); Address _sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted); bool _trySend(const Packet &packet,bool encrypt,uint64_t nwid); @@ -250,15 +252,17 @@ private: struct ContactQueueEntry { ContactQueueEntry() {} - ContactQueueEntry(const SharedPtr<Peer> &p,uint64_t ft,const InetAddress &a) : + ContactQueueEntry(const SharedPtr<Peer> &p,uint64_t ft,int liid,const InetAddress &a) : peer(p), fireAtTime(ft), inaddr(a), + localInterfaceId(liid), strategyIteration(0) {} SharedPtr<Peer> peer; uint64_t fireAtTime; InetAddress inaddr; + int localInterfaceId; unsigned int strategyIteration; }; std::list<ContactQueueEntry> _contactQueue; diff --git a/node/Topology.cpp b/node/Topology.cpp index 25a92acd..c63ed9f4 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -62,7 +62,7 @@ void Topology::setRootServers(const std::map< Identity,std::vector<InetAddress> if (!p) p = SharedPtr<Peer>(new Peer(RR->identity,i->first)); for(std::vector<InetAddress>::const_iterator j(i->second.begin());j!=i->second.end();++j) - p->addPath(RemotePath(*j,true)); + p->addPath(RemotePath(0,*j,true)); p->use(now); _rootPeers.push_back(p); } |