From 93bb934d4e77fd1436ebe81336d396fa769aa59b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Jul 2015 14:08:13 -0700 Subject: Some cleanup, docs, and Path -> Path > RemotePath refactor. --- node/Peer.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'node/Peer.cpp') diff --git a/node/Peer.cpp b/node/Peer.cpp index 96caa72c..cb046b9b 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -46,6 +46,7 @@ Peer::Peer(const Identity &myIdentity,const Identity &peerIdentity) _lastMulticastFrame(0), _lastAnnouncedTo(0), _lastPathConfirmationSent(0), + _lastDirectPathPush(0), _vMajor(0), _vMinor(0), _vRevision(0), @@ -86,7 +87,7 @@ void Peer::received( if (!pathIsConfirmed) { if ((verb == Packet::VERB_OK)&&(inReVerb == Packet::VERB_HELLO)) { // Learn paths if they've been confirmed via a HELLO - Path *slot = (Path *)0; + RemotePath *slot = (RemotePath *)0; if (np < ZT1_MAX_PEER_NETWORK_PATHS) { // Add new path slot = &(_paths[np++]); @@ -101,7 +102,7 @@ void Peer::received( } } if (slot) { - slot->init(remoteAddr,false); + *slot = RemotePath(remoteAddr,false); slot->received(now); _numPaths = np; pathIsConfirmed = true; @@ -193,7 +194,7 @@ void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &at void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) { - Path *const bestPath = getBestPath(now); + RemotePath *const bestPath = getBestPath(now); if ((bestPath)&&(bestPath->active(now))) { if ((now - bestPath->lastReceived()) >= ZT_PEER_DIRECT_PING_DELAY) { TRACE("PING %s(%s)",_id.address().toString().c_str(),bestPath->address().toString().c_str()); @@ -207,7 +208,11 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) } } -void Peer::addPath(const Path &newp) +//void Peer::pushDirectPaths(const std::vector &dps,uint64_t now,bool force) +//{ +//} + +void Peer::addPath(const RemotePath &newp) { unsigned int np = _numPaths; @@ -218,7 +223,7 @@ void Peer::addPath(const Path &newp) } } - Path *slot = (Path *)0; + RemotePath *slot = (RemotePath *)0; if (np < ZT1_MAX_PEER_NETWORK_PATHS) { // Add new path slot = &(_paths[np++]); -- cgit v1.2.3 From 255320e2a6f340fca6c53f3a0516f99a4cb4562b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Jul 2015 14:39:28 -0700 Subject: pushDirectPaths() implementation --- node/Constants.hpp | 5 +++++ node/Packet.hpp | 1 - node/Peer.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++--- node/Peer.hpp | 3 ++- 4 files changed, 67 insertions(+), 5 deletions(-) (limited to 'node/Peer.cpp') diff --git a/node/Constants.hpp b/node/Constants.hpp index ac9dbc99..1f0d8426 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -319,6 +319,11 @@ */ #define ZT_MIN_PATH_CONFIRMATION_INTERVAL 5000 +/** + * Interval between direct path pushes in milliseconds + */ +#define ZT_DIRECT_PATH_PUSH_INTERVAL 300000 + /** * Sanity limit on maximum bridge routes * diff --git a/node/Packet.hpp b/node/Packet.hpp index 14fac1bf..9b86709a 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -892,7 +892,6 @@ public: VERB_SET_EPHEMERAL_KEY = 15, /* Push of potential endpoints for direct communication: - * <[1] flags (unused, must be zero)> * <[2] 16-bit number of paths> * <[...] paths> * diff --git a/node/Peer.cpp b/node/Peer.cpp index cb046b9b..ec04357a 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -208,9 +208,66 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) } } -//void Peer::pushDirectPaths(const std::vector &dps,uint64_t now,bool force) -//{ -//} +void Peer::pushDirectPaths(const RuntimeEnvironment *RR,const std::vector &dps,uint64_t now,bool force) +{ + if (((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force)) { + _lastDirectPathPush = now; + + std::vector::const_iterator p(dps.begin()); + while (p != dps.end()) { + Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS); + outp.addSize(2); // leave room for count + + unsigned int count = 0; + while ((p != dps.end())&&((outp.size() + 24) < ZT_PROTO_MAX_PACKET_LENGTH)) { + uint8_t addressType = 4; + switch(p->address().ss_family) { + case AF_INET: + break; + case AF_INET6: + addressType = 6; + break; + default: + ++p; + continue; + } + + uint8_t flags = 0; + if (p->metric() < 0) + flags |= (0x01 | 0x02); // forget and blacklist + else { + if (p->reliable()) + flags |= 0x04; // no NAT keepalives and such + switch(p->trust()) { + default: + break; + case Path::TRUST_PRIVACY: + flags |= 0x08; // no encryption + break; + case Path::TRUST_ULTIMATE: + flags |= (0x08 | 0x10); // no encryption, no authentication (redundant but go ahead and set both) + break; + } + } + + outp.append(flags); + outp.append((uint8_t)((p->metric() >= 0) ? ((p->metric() <= 255) ? p->metric() : 255) : 0)); + outp.append((uint16_t)0); + outp.append(addressType); + outp.append(p->address().rawIpData(),((addressType == 4) ? 4 : 16)); + outp.append((uint16_t)p->address().port()); + + ++count; + ++p; + } + + if (count) { + outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count); + RR->sw->send(outp,true,0); + } + } + } +} void Peer::addPath(const RemotePath &newp) { diff --git a/node/Peer.hpp b/node/Peer.hpp index 6ca29393..2af3b9e6 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -181,11 +181,12 @@ public: /** * Push direct paths (if within rate limit) * + * @param RR Runtime environment * @param dps Direct paths to me to push to this peer * @param now Current time * @param force If true, force regardless of when we pushed direct paths last */ - void pushDirectPaths(const std::vector &dps,uint64_t now,bool force); + void pushDirectPaths(const RuntimeEnvironment *RR,const std::vector &dps,uint64_t now,bool force); /** * @return All known direct paths to this peer -- cgit v1.2.3 From 79e9a8bcc26491a43577082ec7edb86020f7ec00 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Jul 2015 15:28:48 -0700 Subject: Almost everything for GitHub issue #180 except direct path map setup. --- node/Constants.hpp | 10 ---------- node/IncomingPacket.cpp | 30 ++++++++++++++++++++++++++++++ node/Node.cpp | 16 +--------------- node/Node.hpp | 1 - node/Packet.hpp | 21 +-------------------- node/Peer.cpp | 6 +++++- node/Switch.cpp | 24 ++---------------------- node/Switch.hpp | 2 -- 8 files changed, 39 insertions(+), 71 deletions(-) (limited to 'node/Peer.cpp') diff --git a/node/Constants.hpp b/node/Constants.hpp index 1f0d8426..d15fef13 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -304,16 +304,6 @@ */ #define ZT_ANTIRECURSION_HISTORY_SIZE 16 -/** - * How often to send LAN beacons - */ -#define ZT_BEACON_INTERVAL 30000 - -/** - * Do not respond to any beacon more often than this - */ -#define ZT_MIN_BEACON_RESPONSE_INTERVAL 2500 - /** * Minimum delay between attempts to confirm new paths to peers (to avoid HELLO flooding) */ diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 7634f54f..87669ba7 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -885,6 +885,36 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const SharedPtr &peer) { + try { + unsigned int count = at(ZT_PACKET_IDX_PAYLOAD); + unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 2; + + while (count) { // if ptr overflows Buffer will throw + unsigned int flags = (*this)[ptr++]; + /*int metric = (*this)[ptr++];*/ ++ptr; + unsigned int extLen = at(ptr); ptr += 2; + ptr += extLen; // unused right now + unsigned int addrType = (*this)[ptr++]; + unsigned int addrLen = (*this)[ptr++]; + switch(addrType) { + case 4: { + InetAddress a(field(ptr,4),4,at(ptr + 4)); + if ((flags & (0x01 | 0x02)) == 0) + peer->attemptToContactAt(RR,a,RR->node->now()); + } break; + case 6: { + InetAddress a(field(ptr,16),16,at(ptr + 16)); + if ((flags & (0x01 | 0x02)) == 0) + peer->attemptToContactAt(RR,a,RR->node->now()); + } break; + } + ptr += addrLen; + } + } catch (std::exception &exc) { + TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); + } catch ( ... ) { + TRACE("dropped PUSH_DIRECT_PATHS from %s(%s): unexpected exception: (unknown)",source().toString().c_str(),_remoteAddress.toString().c_str()); + } return true; } diff --git a/node/Node.cpp b/node/Node.cpp index 8eacf753..7c70db97 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -78,8 +78,7 @@ Node::Node( _networks_m(), _now(now), _lastPingCheck(0), - _lastHousekeepingRun(0), - _lastBeacon(0) + _lastHousekeepingRun(0) { _newestVersionSeen[0] = ZEROTIER_ONE_VERSION_MAJOR; _newestVersionSeen[1] = ZEROTIER_ONE_VERSION_MINOR; @@ -269,19 +268,6 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next _online = ((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT); if (oldOnline != _online) postEvent(_online ? ZT1_EVENT_ONLINE : ZT1_EVENT_OFFLINE); - - // Send LAN beacons - if ((now - _lastBeacon) >= ZT_BEACON_INTERVAL) { - _lastBeacon = now; - char beacon[13]; - void *p = beacon; - *(reinterpret_cast(p)) = RR->prng->next32(); - p = beacon + 4; - *(reinterpret_cast(p)) = RR->prng->next32(); - RR->identity.address().copyTo(beacon + 8,5); - RR->antiRec->logOutgoingZT(beacon,13); - putPacket(ZT_DEFAULTS.v4Broadcast,beacon,13); - } } catch ( ... ) { return ZT1_RESULT_FATAL_ERROR_INTERNAL; } diff --git a/node/Node.hpp b/node/Node.hpp index 5c7cfae2..cd8d68fc 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -251,7 +251,6 @@ private: uint64_t _now; uint64_t _lastPingCheck; uint64_t _lastHousekeepingRun; - uint64_t _lastBeacon; unsigned int _newestVersionSeen[3]; // major, minor, revision bool _online; }; diff --git a/node/Packet.hpp b/node/Packet.hpp index 9b86709a..50471b06 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -233,16 +233,6 @@ */ #define ZT_PROTO_MIN_FRAGMENT_LENGTH ZT_PACKET_FRAGMENT_IDX_PAYLOAD -/** - * DEPRECATED: length of LAN beacon packets - */ -#define ZT_PROTO_BEACON_LENGTH 13 - -/** - * DEPRECATED: index of address in a LAN beacon - */ -#define ZT_PROTO_BEACON_IDX_ADDRESS 8 - // Destination address types from HELLO, OK(HELLO), and other message types #define ZT_PROTO_DEST_ADDRESS_TYPE_NONE 0 #define ZT_PROTO_DEST_ADDRESS_TYPE_ZEROTIER 1 // reserved but unused @@ -388,16 +378,6 @@ namespace ZeroTier { * * For unencrypted packets, MAC is computed on plaintext. Only HELLO is ever * sent in the clear, as it's the "here is my public key" message. - * - * Beacon format and beacon packets: - * <[8] 8 random bytes> - * <[5] sender ZT address> - * - * A beacon is a 13-byte packet containing only the address of the sender. - * Receiving peers may or may not respond to beacons with a HELLO or other - * message to initiate direct communication. - * - * Beacons may be used for direct LAN announcement or NAT traversal. */ class Packet : public Buffer { @@ -901,6 +881,7 @@ public: * <[2] length of extended path characteristics or 0 for none> * <[...] extended path characteristics> * <[1] address type> + * <[1] address length in bytes> * <[...] address> * * Path record flags: diff --git a/node/Peer.cpp b/node/Peer.cpp index ec04357a..225fbdef 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -210,9 +210,12 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) void Peer::pushDirectPaths(const RuntimeEnvironment *RR,const std::vector &dps,uint64_t now,bool force) { - if (((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force)) { + if ((!dps.empty())&&(((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force))) { _lastDirectPathPush = now; + TRACE("pushing %u direct paths to %s",(unsigned int)dps.size(),_id.address().toString().c_str()); + printf("pushing %u direct paths to %s",(unsigned int)dps.size(),_id.address().toString().c_str()); + std::vector::const_iterator p(dps.begin()); while (p != dps.end()) { Packet outp(_id.address(),RR->identity.address(),Packet::VERB_PUSH_DIRECT_PATHS); @@ -254,6 +257,7 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,const std::vector outp.append((uint8_t)((p->metric() >= 0) ? ((p->metric() <= 255) ? p->metric() : 255) : 0)); outp.append((uint16_t)0); outp.append(addressType); + outp.append((addressType == 4) ? 6 : 18); outp.append(p->address().rawIpData(),((addressType == 4) ? 4 : 16)); outp.append((uint16_t)p->address().port()); diff --git a/node/Switch.cpp b/node/Switch.cpp index 7600624f..6a0b07cd 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -49,8 +49,7 @@ namespace ZeroTier { Switch::Switch(const RuntimeEnvironment *renv) : - RR(renv), - _lastBeacon(0) + RR(renv) { } @@ -61,9 +60,7 @@ Switch::~Switch() void Switch::onRemotePacket(const InetAddress &fromAddr,const void *data,unsigned int len) { try { - if (len == ZT_PROTO_BEACON_LENGTH) { - _handleBeacon(fromAddr,Buffer(data,len)); - } else if (len > ZT_PROTO_MIN_FRAGMENT_LENGTH) { + 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); } else if (len >= ZT_PROTO_MIN_PACKET_LENGTH) { @@ -696,23 +693,6 @@ void Switch::_handleRemotePacketHead(const InetAddress &fromAddr,const void *dat } } -void Switch::_handleBeacon(const InetAddress &fromAddr,const Buffer &data) -{ - Address beaconAddr(data.field(ZT_PROTO_BEACON_IDX_ADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); - if (beaconAddr == RR->identity.address()) - return; - SharedPtr peer(RR->topology->getPeer(beaconAddr)); - if (peer) { - const uint64_t now = RR->node->now(); - if ((now - _lastBeacon) >= ZT_MIN_BEACON_RESPONSE_INTERVAL) { - _lastBeacon = now; - Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP); - outp.armor(peer->key(),false); - RR->node->putPacket(fromAddr,outp.data(),outp.size()); - } - } -} - Address Switch::_sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted) { SharedPtr root(RR->topology->getBestRoot(peersAlreadyConsulted,numPeersAlreadyConsulted,false)); diff --git a/node/Switch.hpp b/node/Switch.hpp index 0ba4c138..af6e5938 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -183,12 +183,10 @@ public: private: void _handleRemotePacketFragment(const InetAddress &fromAddr,const void *data,unsigned int len); void _handleRemotePacketHead(const InetAddress &fromAddr,const void *data,unsigned int len); - void _handleBeacon(const InetAddress &fromAddr,const Buffer &data); Address _sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted); bool _trySend(const Packet &packet,bool encrypt,uint64_t nwid); const RuntimeEnvironment *const RR; - volatile uint64_t _lastBeacon; // Outsanding WHOIS requests and how many retries they've undergone struct WhoisRequest -- cgit v1.2.3 From a87cd2d0941d5cf6b88f630159946ae66d3e464e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Jul 2015 16:32:34 -0700 Subject: Unix side of local interface address awareness for GitHub issue #180. --- node/InetAddress.cpp | 8 +++++- node/Peer.cpp | 1 - service/OneService.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) (limited to 'node/Peer.cpp') diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 83de36d4..91bfbed6 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -91,7 +91,13 @@ InetAddress::IpScope InetAddress::ipScope() const const unsigned char *ip = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); if ((ip[0] & 0xf0) == 0xf0) { if (ip[0] == 0xff) return IP_SCOPE_MULTICAST; // ff00::/8 - if ((ip[0] == 0xfe)&&((ip[1] & 0xc0) == 0x80)) return IP_SCOPE_LINK_LOCAL; // fe80::/10 + if ((ip[0] == 0xfe)&&((ip[1] & 0xc0) == 0x80)) { + unsigned int k = 2; + while ((!ip[k])&&(k < 15)) ++k; + if ((k == 15)&&(ip[15] == 0x01)) + return IP_SCOPE_LOOPBACK; // fe80::1/128 + else return IP_SCOPE_LINK_LOCAL; // fe80::/10 + } if ((ip[0] & 0xfe) == 0xfc) return IP_SCOPE_PRIVATE; // fc00::/7 } unsigned int k = 0; diff --git a/node/Peer.cpp b/node/Peer.cpp index 225fbdef..f5fdf7dd 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -214,7 +214,6 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,const std::vector _lastDirectPathPush = now; TRACE("pushing %u direct paths to %s",(unsigned int)dps.size(),_id.address().toString().c_str()); - printf("pushing %u direct paths to %s",(unsigned int)dps.size(),_id.address().toString().c_str()); std::vector::const_iterator p(dps.begin()); while (p != dps.end()) { diff --git a/service/OneService.cpp b/service/OneService.cpp index 7532bf75..109050bf 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -78,8 +78,10 @@ class SqliteNetworkController; #include #else #include +#include #include #include +#include #endif // Include the right tap device driver for this platform -- add new platforms here @@ -123,6 +125,9 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } // Attempt to engage TCP fallback after this many ms of no reply to packets sent to global-scope IPs #define ZT1_TCP_FALLBACK_AFTER 60000 +// How often to check for local interface addresses +#define ZT1_LOCAL_INTERFACE_CHECK_INTERVAL 300000 + namespace ZeroTier { namespace { @@ -405,6 +410,7 @@ public: _nextBackgroundTaskDeadline(0), _tcpFallbackTunnel((TcpConnection *)0), _termReason(ONE_STILL_RUNNING), + _port(port), _run(true) { struct sockaddr_in in4; @@ -501,6 +507,7 @@ public: _lastRestart = clockShouldBe; uint64_t lastTapMulticastGroupCheck = 0; uint64_t lastTcpFallbackResolve = 0; + uint64_t lastLocalInterfaceAddressCheck = 0; #ifdef ZT_AUTO_UPDATE uint64_t lastSoftwareUpdateCheck = 0; #endif // ZT_AUTO_UPDATE @@ -554,6 +561,66 @@ public: } } + if ((now - lastLocalInterfaceAddressCheck) >= ZT1_LOCAL_INTERFACE_CHECK_INTERVAL) { + lastLocalInterfaceAddressCheck = now; + +#ifdef __UNIX_LIKE__ + std::vector ztDevices; + { + Mutex::Lock _l(_taps_m); + for(std::map< uint64_t,EthernetTap *>::const_iterator t(_taps.begin());t!=_taps.end();++t) + ztDevices.push_back(t->second->deviceName()); + } + + struct ifaddrs *ifatbl = (struct ifaddrs *)0; + if ((getifaddrs(&ifatbl) == 0)&&(ifatbl)) { + _node->clearLocalInterfaceAddresses(); + struct ifaddrs *ifa = ifatbl; + while (ifa) { + if ((ifa->ifa_name)&&(ifa->ifa_addr)) { + bool isZT = false; + for(std::vector::const_iterator d(ztDevices.begin());d!=ztDevices.end();++d) { + if (*d == ifa->ifa_name) { + isZT = true; + break; + } + } + if (!isZT) { + InetAddress ip(ifa->ifa_addr); + if ((ip.ss_family == AF_INET)||(ip.ss_family == AF_INET6)) { + switch(ip.ipScope()) { + case InetAddress::IP_SCOPE_LINK_LOCAL: + case InetAddress::IP_SCOPE_PRIVATE: + case InetAddress::IP_SCOPE_PSEUDOPRIVATE: + case InetAddress::IP_SCOPE_SHARED: + case InetAddress::IP_SCOPE_GLOBAL: + ip.setPort(_port); + _node->addLocalInterfaceAddress(reinterpret_cast(&ip),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL,0); + break; + default: + break; + } + } + } + } + ifa = ifa->ifa_next; + } + freeifaddrs(ifatbl); + } +#endif // __UNIX_LIKE__ + +#ifdef __WINDOWS__ + std::vector ztDevices; + { + Mutex::Lock _l(_taps_m); + for(std::map< uint64_t,EthernetTap *>::const_iterator t(_taps.begin());t!=_taps.end();++t) + ztDevices.push_back(t->second->deviceName()); + } + + // TODO +#endif // __WINDOWS__ + } + const unsigned long delay = (dl > now) ? (unsigned long)(dl - now) : 100; clockShouldBe = now + (uint64_t)delay; _phy.poll(delay); @@ -1158,6 +1225,8 @@ private: std::string _fatalErrorMessage; Mutex _termReason_m; + unsigned int _port; + bool _run; Mutex _run_m; }; -- cgit v1.2.3 From 84ba365c77fafd9190d258ec364e9e06b9249764 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Jul 2015 17:20:41 -0700 Subject: Fix bug in direct path push send. --- node/Peer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'node/Peer.cpp') diff --git a/node/Peer.cpp b/node/Peer.cpp index f5fdf7dd..7c936d4a 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -256,7 +256,7 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,const std::vector outp.append((uint8_t)((p->metric() >= 0) ? ((p->metric() <= 255) ? p->metric() : 255) : 0)); outp.append((uint16_t)0); outp.append(addressType); - outp.append((addressType == 4) ? 6 : 18); + outp.append((uint8_t)((addressType == 4) ? 6 : 18)); outp.append(p->address().rawIpData(),((addressType == 4) ? 4 : 16)); outp.append((uint16_t)p->address().port()); -- cgit v1.2.3 From 778c7e6e703353030e2ea130e3db7cc968a5d53c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 7 Jul 2015 10:00:34 -0700 Subject: More cleanup to direct path push, comment fixes, etc. --- node/IncomingPacket.cpp | 17 +------- node/Network.hpp | 2 +- node/OutboundMulticast.cpp | 8 +--- node/Packet.hpp | 8 ++-- node/Peer.cpp | 10 +++-- node/Peer.hpp | 8 ++-- node/Switch.cpp | 98 +++++++++++++++++++++++----------------------- node/Switch.hpp | 5 ++- 8 files changed, 71 insertions(+), 85 deletions(-) (limited to 'node/Peer.cpp') diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 7e883221..d5b4e9e6 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -661,21 +661,8 @@ bool IncomingPacket::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment ptr += com.deserialize(*this,ptr); if (com.hasRequiredFields()) { SharedPtr network(RR->node->network(com.networkId())); - if (network) { - if (network->validateAndAddMembershipCertificate(com)) { - if ((network->isAllowed(peer->address()))&&(network->peerNeedsOurMembershipCertificate(peer->address(),RR->node->now()))) { - // If peer passed our check and we haven't sent it our cert yet, respond - // and push our cert as well for instant authorization setup. - SharedPtr nconf(network->config2()); - if ((nconf)&&(nconf->com())) { - 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()); - } - } - } - } + if (network) + network->validateAndAddMembershipCertificate(com); } } diff --git a/node/Network.hpp b/node/Network.hpp index 53a22dcd..d7320d46 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -184,7 +184,7 @@ public: bool validateAndAddMembershipCertificate(const CertificateOfMembership &cert); /** - * Check if we should push membership certificate to a peer, and update last pushed + * Check if we should push membership certificate to a peer, AND update last pushed * * If we haven't pushed a cert to this peer in a long enough time, this returns * true and updates the last pushed time. Otherwise it returns false. diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 5809504a..46116c07 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -102,13 +102,9 @@ void OutboundMulticast::init( void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,const Address &toAddr) { - SharedPtr network(RR->node->network(_nwid)); - - if (!network) - return; - if (_haveCom) { - if (network->peerNeedsOurMembershipCertificate(toAddr,RR->node->now())) { + SharedPtr network(RR->node->network(_nwid)); + if ((network)&&(network->peerNeedsOurMembershipCertificate(toAddr,RR->node->now()))) { _packetWithCom.newInitializationVector(); _packetWithCom.setDestination(toAddr); //TRACE(">>MC %.16llx -> %s (with COM)",(unsigned long long)this,toAddr.toString().c_str()); diff --git a/node/Packet.hpp b/node/Packet.hpp index 9787edb7..e84306c2 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -678,10 +678,10 @@ public: * <[...] serialized certificate of membership> * [ ... additional certificates may follow ...] * - * OK/ERROR are not generated, but the recipient should push its network - * membership certificate if the certificate the peer pushed is valid - * and agrees and if it hasn't done so in too long. This ensures instant - * network authentication setup between valid and authorized peers. + * This is sent in response to ERROR_NEED_MEMBERSHIP_CERTIFICATE and may + * be pushed at any other time to keep exchanged certificates up to date. + * + * OK/ERROR are not generated. */ VERB_NETWORK_MEMBERSHIP_CERTIFICATE = 10, diff --git a/node/Peer.cpp b/node/Peer.cpp index 7c936d4a..84aa8bef 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -208,12 +208,13 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) } } -void Peer::pushDirectPaths(const RuntimeEnvironment *RR,const std::vector &dps,uint64_t now,bool force) +void Peer::pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_t now,bool force) { - if ((!dps.empty())&&(((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force))) { + if ((((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force))) { _lastDirectPathPush = now; - TRACE("pushing %u direct paths to %s",(unsigned int)dps.size(),_id.address().toString().c_str()); + std::vector dps(RR->node->directPaths()); + TRACE("pushing %u direct paths (local interface addresses) to %s",(unsigned int)dps.size(),_id.address().toString().c_str()); std::vector::const_iterator p(dps.begin()); while (p != dps.end()) { @@ -266,7 +267,8 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,const std::vector if (count) { outp.setAt(ZT_PACKET_IDX_PAYLOAD,(uint16_t)count); - RR->sw->send(outp,true,0); + outp.armor(_key,true); + path->send(RR,outp.data(),outp.size(),now); } } } diff --git a/node/Peer.hpp b/node/Peer.hpp index 2af3b9e6..f5118794 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -179,14 +179,14 @@ public: void doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now); /** - * Push direct paths (if within rate limit) + * Push direct paths if we haven't done so in [rate limit] milliseconds * * @param RR Runtime environment - * @param dps Direct paths to me to push to this peer + * @param path Remote path to use to send the push * @param now Current time - * @param force If true, force regardless of when we pushed direct paths last + * @param force If true, push regardless of rate limit */ - void pushDirectPaths(const RuntimeEnvironment *RR,const std::vector &dps,uint64_t now,bool force); + void pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_t now,bool force); /** * @return All known direct paths to this peer diff --git a/node/Switch.cpp b/node/Switch.cpp index 201f36d1..13070be1 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -162,38 +162,34 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c if (to[0] == MAC::firstOctetForNetwork(network->id())) { // Destination is another ZeroTier peer on the same network - Address toZT(to.toAddress(network->id())); - if (network->isAllowed(toZT)) { - const bool includeCom = network->peerNeedsOurMembershipCertificate(toZT,RR->node->now()); - if ((fromBridged)||(includeCom)) { - Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME); - outp.append(network->id()); - if (includeCom) { - outp.append((unsigned char)0x01); // 0x01 -- COM included - nconf->com().serialize(outp); - } else { - outp.append((unsigned char)0x00); - } - to.appendTo(outp); - from.appendTo(outp); - outp.append((uint16_t)etherType); - outp.append(data,len); - outp.compress(); - send(outp,true,network->id()); + Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this + const bool includeCom = network->peerNeedsOurMembershipCertificate(toZT,RR->node->now()); + if ((fromBridged)||(includeCom)) { + Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME); + outp.append(network->id()); + if (includeCom) { + outp.append((unsigned char)0x01); // 0x01 -- COM included + nconf->com().serialize(outp); } else { - Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME); - outp.append(network->id()); - outp.append((uint16_t)etherType); - outp.append(data,len); - outp.compress(); - send(outp,true,network->id()); + outp.append((unsigned char)0x00); } - - //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); + to.appendTo(outp); + from.appendTo(outp); + outp.append((uint16_t)etherType); + outp.append(data,len); + outp.compress(); + send(outp,true,network->id()); } else { - TRACE("%.16llx: UNICAST: %s -> %s etherType==%s dropped, destination not a member of private network",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType)); + Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME); + outp.append(network->id()); + outp.append((uint16_t)etherType); + outp.append(data,len); + outp.compress(); + send(outp,true,network->id()); } + //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; } @@ -205,7 +201,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c /* Create an array of up to ZT_MAX_BRIDGE_SPAM recipients for this bridged frame. */ bridges[0] = network->findBridgeTo(to); - if ((bridges[0])&&(bridges[0] != RR->identity.address())&&(network->isAllowed(bridges[0]))&&(network->permitsBridging(bridges[0]))) { + if ((bridges[0])&&(bridges[0] != RR->identity.address())&&(network->permitsBridging(bridges[0]))) { /* We have a known bridge route for this MAC, send it there. */ ++numBridges; } else if (!nconf->activeBridges().empty()) { @@ -215,8 +211,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c if (nconf->activeBridges().size() <= ZT_MAX_BRIDGE_SPAM) { // If there are <= ZT_MAX_BRIDGE_SPAM active bridges, spam them all while (ab != nconf->activeBridges().end()) { - if (network->isAllowed(*ab)) // config sanity check - bridges[numBridges++] = *ab; + bridges[numBridges++] = *ab; ++ab; } } else { @@ -225,8 +220,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c if (ab == nconf->activeBridges().end()) ab = nconf->activeBridges().begin(); if (((unsigned long)RR->prng->next32() % (unsigned long)nconf->activeBridges().size()) == 0) { - if (network->isAllowed(*ab)) // config sanity check - bridges[numBridges++] = *ab; + bridges[numBridges++] = *ab; ++ab; } else ++ab; } @@ -703,29 +697,28 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid) if (peer) { const uint64_t now = RR->node->now(); + SharedPtr network; + SharedPtr nconf; if (nwid) { - // If this packet has an associated network, give the peer additional hints for direct connectivity - peer->pushDirectPaths(RR,RR->node->directPaths(),now,false); + network = RR->node->network(nwid); + if (!network) + return false; // we probably just left this network, let its packets die + nconf = network->config2(); + if (!nconf) + return false; // sanity check: unconfigured network? why are we trying to talk to it? } RemotePath *viaPath = peer->getBestPath(now); + SharedPtr relay; if (!viaPath) { - SharedPtr relay; - // See if this network has a preferred relay (if packet has an associated network) - if (nwid) { - SharedPtr network(RR->node->network(nwid)); - if (network) { - SharedPtr nconf(network->config2()); - if (nconf) { - unsigned int latency = ~((unsigned int)0); - for(std::vector< std::pair >::const_iterator r(nconf->relays().begin());r!=nconf->relays().end();++r) { - if (r->first != peer->address()) { - SharedPtr rp(RR->topology->getPeer(r->first)); - if ((rp)&&(rp->hasActiveDirectPath(now))&&(rp->latency() <= latency)) - rp.swap(relay); - } - } + if (nconf) { + unsigned int latency = ~((unsigned int)0); + for(std::vector< std::pair >::const_iterator r(nconf->relays().begin());r!=nconf->relays().end();++r) { + if (r->first != peer->address()) { + SharedPtr rp(RR->topology->getPeer(r->first)); + if ((rp)&&(rp->hasActiveDirectPath(now))&&(rp->latency() <= latency)) + rp.swap(relay); } } } @@ -735,7 +728,12 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid) relay = RR->topology->getBestRoot(); if (!(relay)||(!(viaPath = relay->getBestPath(now)))) - return false; + return false; // no paths, no root servers? + } + + if ((network)&&(relay)&&(network->isAllowed(peer->address()))) { + // Push hints for direct connectivity to this peer if we are relaying + peer->pushDirectPaths(RR,viaPath,now,false); } Packet tmp(packet); diff --git a/node/Switch.hpp b/node/Switch.hpp index af6e5938..95ca362c 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -108,10 +108,13 @@ public: * * Needless to say, the packet's source must be this node. Otherwise it * won't be encrypted right. (This is not used for relaying.) + * + * The network ID should only be specified for frames and other actual + * network traffic. * * @param packet Packet to send * @param encrypt Encrypt packet payload? (always true except for HELLO) - * @param nwid Network ID or 0 if message is not related to a specific network + * @param nwid Related network ID or 0 if message is not in-network traffic */ void send(const Packet &packet,bool encrypt,uint64_t nwid); -- cgit v1.2.3