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. --- service/OneService.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'service/OneService.cpp') 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 f881cdd7675fc861ea6696837ab6e8ea650c036e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Jul 2015 17:22:37 -0700 Subject: Add new .h file to VS build, and Windows side of local interface address enumeration. --- node/IncomingPacket.cpp | 8 +++-- service/OneService.cpp | 43 +++++++++++++++++++++++-- windows/ZeroTierOne/ZeroTierOne.vcxproj | 1 + windows/ZeroTierOne/ZeroTierOne.vcxproj.filters | 3 ++ 4 files changed, 51 insertions(+), 4 deletions(-) (limited to 'service/OneService.cpp') diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 87669ba7..c1594f81 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -899,13 +899,17 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha switch(addrType) { case 4: { InetAddress a(field(ptr,4),4,at(ptr + 4)); - if ((flags & (0x01 | 0x02)) == 0) + if ((flags & (0x01 | 0x02)) == 0) { + printf("contacting %s at %s\r\n",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(RR,a,RR->node->now()); + } } break; case 6: { InetAddress a(field(ptr,16),16,at(ptr + 16)); - if ((flags & (0x01 | 0x02)) == 0) + if ((flags & (0x01 | 0x02)) == 0) { + printf("contacting %s at %s\r\n",peer->address().toString().c_str(),a.toString().c_str()); peer->attemptToContactAt(RR,a,RR->node->now()); + } } break; } ptr += addrLen; diff --git a/service/OneService.cpp b/service/OneService.cpp index 109050bf..527ac1b0 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -75,7 +75,11 @@ class SqliteNetworkController; #endif // ZT_ENABLE_NETWORK_CONTROLLER #ifdef __WINDOWS__ +#include +#include #include +#include +#include #else #include #include @@ -614,10 +618,45 @@ public: { 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()); + ztDevices.push_back(t->second->luid()); } - // TODO + char aabuf[16384]; + ULONG aalen = sizeof(aabuf); + if (GetAdaptersAddresses(AF_UNSPEC,GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER,(void *)0,reinterpret_cast(aabuf),&aalen) == NO_ERROR) { + PIP_ADAPTER_ADDRESSES a = reinterpret_cast(aabuf); + while (a) { + bool isZT = false; + for(std::vector::const_iterator d(ztDevices.begin());d!=ztDevices.end();++d) { + if (a->Luid.Value == d->Value) { + isZT = true; + break; + } + } + if (!isZT) { + PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress; + while (ua) { + InetAddress ip(ua->Address.lpSockaddr); + 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; + } + } + ua = ua->Next; + } + } + a = a->Next; + } + } #endif // __WINDOWS__ } diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj index acd4c7fe..554669b6 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj @@ -94,6 +94,7 @@ + diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters index 9337a88e..f36b5dc0 100644 --- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters +++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters @@ -344,6 +344,9 @@ Header Files\osdep + + Header Files\node + -- cgit v1.2.3 From 91fa643131fea5ace3daff6b42b9af7d25db5464 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Jul 2015 17:36:58 -0700 Subject: Minor fix to Windows local adapter address enumeration. --- service/OneService.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 527ac1b0..6f6eabe2 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -645,6 +645,7 @@ public: case InetAddress::IP_SCOPE_SHARED: case InetAddress::IP_SCOPE_GLOBAL: ip.setPort(_port); + printf("found %s on %S\r\n",ip.toString().c_str(),a->FriendlyName); _node->addLocalInterfaceAddress(reinterpret_cast(&ip),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL,0); break; default: -- cgit v1.2.3 From 25a067c8c3a4987c3366c3f9e8b4d9f5743db71c Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 6 Jul 2015 17:37:32 -0700 Subject: Eliminate debug printf(). --- service/OneService.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'service/OneService.cpp') diff --git a/service/OneService.cpp b/service/OneService.cpp index 6f6eabe2..527ac1b0 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -645,7 +645,6 @@ public: case InetAddress::IP_SCOPE_SHARED: case InetAddress::IP_SCOPE_GLOBAL: ip.setPort(_port); - printf("found %s on %S\r\n",ip.toString().c_str(),a->FriendlyName); _node->addLocalInterfaceAddress(reinterpret_cast(&ip),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL,0); break; default: -- cgit v1.2.3 From c863ff3f02e9d68eb9bea32160d252eaddb7f1f5 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 7 Jul 2015 08:54:48 -0700 Subject: A bunch of comments and cleanup, including some to yesterday's direct path pushing changes. Move path viability check to one place, and stop trying to use link-local addresses since they are not reliable. --- include/ZeroTierOne.h | 9 ++++++- node/IncomingPacket.cpp | 66 +++++++++++++++++++++++++++++++++++-------------- node/Node.cpp | 24 +++++++++++------- node/Node.hpp | 2 +- node/Packet.hpp | 7 +++--- node/Path.hpp | 33 +++++++++++++++++++++++++ service/OneService.cpp | 32 +++--------------------- 7 files changed, 112 insertions(+), 61 deletions(-) (limited to 'service/OneService.cpp') diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 4790795e..446bbc77 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -978,12 +978,19 @@ void ZT1_Node_freeQueryResult(ZT1_Node *node,void *qr); * Take care that these are never ZeroTier interface addresses, otherwise * strange things might happen or they simply won't work. * + * This returns a boolean indicating whether or not the address was + * accepted. ZeroTier will only communicate over certain address types + * and (for IP) address classes. Thus it's safe to just dump your OS's + * entire remote IP list (excluding ZeroTier interface IPs) into here + * and let ZeroTier determine which addresses it will use. + * * @param addr Local interface address * @param metric Local interface metric * @param trust How much do you trust the local network under this interface? * @param reliable If nonzero, this interface doesn't link to anything behind a NAT or stateful firewall + * @return Boolean: non-zero if address was accepted and added */ -void ZT1_Node_addLocalInterfaceAddress(ZT1_Node *node,const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable); +int ZT1_Node_addLocalInterfaceAddress(ZT1_Node *node,const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable); /** * Clear local interface addresses diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 80159194..7e883221 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -134,6 +134,9 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr break; case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: { + /* Note: certificates are public so it's safe to push them to anyone + * who asks. We won't communicate unless we also get a certificate + * from the remote that agrees. */ SharedPtr network(RR->node->network(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); if (network) { SharedPtr nconf(network->config2()); @@ -170,8 +173,20 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) { + /* Note: this is the only packet ever sent in the clear, and it's also + * the only packet that we authenticate via a different path. Authentication + * occurs here and is based on the validity of the identity and the + * integrity of the packet's MAC, but it must be done after we check + * the identity since HELLO is a mechanism for learning new identities + * in the first place. */ + try { const unsigned int protoVersion = (*this)[ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION]; + if (protoVersion < ZT_PROTO_VERSION_MIN) { + TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_remoteAddress.toString().c_str()); + return true; + } + const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION]; const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION]; const unsigned int vRevision = at(ZT_PROTO_VERB_HELLO_IDX_REVISION); @@ -179,6 +194,10 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) Identity id; unsigned int destAddrPtr = id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY) + ZT_PROTO_VERB_HELLO_IDX_IDENTITY; + if (source() != id.address()) { + TRACE("dropped HELLO from %s(%s): identity not for sending address",source().toString().c_str(),_remoteAddress.toString().c_str()); + return true; + } InetAddress destAddr; if (destAddrPtr < size()) { // ZeroTier One < 1.0.3 did not include this field @@ -193,16 +212,6 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) } } - if (source() != id.address()) { - TRACE("dropped HELLO from %s(%s): identity not for sending address",source().toString().c_str(),_remoteAddress.toString().c_str()); - return true; - } - - if (protoVersion < ZT_PROTO_VERSION_MIN) { - TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_remoteAddress.toString().c_str()); - return true; - } - SharedPtr peer(RR->topology->getPeer(id.address())); if (peer) { // We already have an identity with this address -- check for collisions @@ -245,12 +254,14 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) } else { // We don't already have an identity with this address -- validate and learn it + // Check identity proof of work if (!id.locallyValidate()) { RR->node->postEvent(ZT1_EVENT_AUTHENTICATION_FAILURE,(const void *)&_remoteAddress); TRACE("dropped HELLO from %s(%s): identity invalid",id.address().toString().c_str(),_remoteAddress.toString().c_str()); return true; } + // Check packet integrity and authentication SharedPtr newPeer(new Peer(RR->identity,id)); if (!dearmor(newPeer->key())) { RR->node->postEvent(ZT1_EVENT_AUTHENTICATION_FAILURE,(const void *)&_remoteAddress); @@ -554,14 +565,17 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr

validateAndAddMembershipCertificate(com); + if (com.hasRequiredFields()) { + if (!network->validateAndAddMembershipCertificate(com)) + comFailed = true; // technically this check is redundant to isAllowed(), but do it anyway for thoroughness + } } - if (!network->isAllowed(peer->address())) { + if ((comFailed)||(!network->isAllowed(peer->address()))) { TRACE("dropped EXT_FRAME from %s(%s): not a member of private network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),network->id()); _sendErrorNeedCertificate(RR,peer,network->id()); return true; @@ -647,8 +661,21 @@ bool IncomingPacket::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment ptr += com.deserialize(*this,ptr); if (com.hasRequiredFields()) { SharedPtr network(RR->node->network(com.networkId())); - if (network) - network->validateAndAddMembershipCertificate(com); + 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()); + } + } + } + } } } @@ -890,24 +917,25 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const Sha unsigned int ptr = ZT_PACKET_IDX_PAYLOAD + 2; while (count) { // if ptr overflows Buffer will throw + // TODO: properly handle blacklisting, support other features... see Packet.hpp. + 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) { + if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) ) peer->attemptToContactAt(RR,a,RR->node->now()); - } } break; case 6: { InetAddress a(field(ptr,16),16,at(ptr + 16)); - if ((flags & (0x01 | 0x02)) == 0) { + if ( ((flags & (0x01 | 0x02)) == 0) && (Path::isAddressValidForPath(a)) ) peer->attemptToContactAt(RR,a,RR->node->now()); - } } break; } ptr += addrLen; diff --git a/node/Node.cpp b/node/Node.cpp index 057dc285..d8bd8910 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -426,12 +426,16 @@ void Node::freeQueryResult(void *qr) ::free(qr); } -void Node::addLocalInterfaceAddress(const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable) -{ - Mutex::Lock _l(_directPaths_m); - _directPaths.push_back(Path(*(reinterpret_cast(addr)),metric,(Path::Trust)trust,reliable != 0)); - std::sort(_directPaths.begin(),_directPaths.end()); - _directPaths.erase(std::unique(_directPaths.begin(),_directPaths.end()),_directPaths.end()); +int Node::addLocalInterfaceAddress(const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable) +{ + if (Path::isAddressValidForPath(*(reinterpret_cast(addr)))) { + Mutex::Lock _l(_directPaths_m); + _directPaths.push_back(Path(*(reinterpret_cast(addr)),metric,(Path::Trust)trust,reliable != 0)); + std::sort(_directPaths.begin(),_directPaths.end()); + _directPaths.erase(std::unique(_directPaths.begin(),_directPaths.end()),_directPaths.end()); + return 1; + } + return 0; } void Node::clearLocalInterfaceAddresses() @@ -693,11 +697,13 @@ void ZT1_Node_setNetconfMaster(ZT1_Node *node,void *networkControllerInstance) } catch ( ... ) {} } -void ZT1_Node_addLocalInterfaceAddress(ZT1_Node *node,const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable) +int ZT1_Node_addLocalInterfaceAddress(ZT1_Node *node,const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable) { try { - reinterpret_cast(node)->addLocalInterfaceAddress(addr,metric,trust,reliable); - } catch ( ... ) {} + return reinterpret_cast(node)->addLocalInterfaceAddress(addr,metric,trust,reliable); + } catch ( ... ) { + return 0; + } } void ZT1_Node_clearLocalInterfaceAddresses(ZT1_Node *node) diff --git a/node/Node.hpp b/node/Node.hpp index 1c260545..fe31576c 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -104,7 +104,7 @@ public: ZT1_VirtualNetworkConfig *networkConfig(uint64_t nwid) const; ZT1_VirtualNetworkList *networks() const; void freeQueryResult(void *qr); - void addLocalInterfaceAddress(const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable); + int addLocalInterfaceAddress(const struct sockaddr_storage *addr,int metric,ZT1_LocalInterfaceAddressTrust trust,int reliable); void clearLocalInterfaceAddresses(); void setNetconfMaster(void *networkControllerInstance); diff --git a/node/Packet.hpp b/node/Packet.hpp index 51a241ba..9787edb7 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -678,9 +678,10 @@ public: * <[...] serialized certificate of membership> * [ ... additional certificates may follow ...] * - * Certificate contains network ID, peer it was issued for, etc. - * - * OK/ERROR are not generated. + * 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. */ VERB_NETWORK_MEMBERSHIP_CERTIFICATE = 10, diff --git a/node/Path.hpp b/node/Path.hpp index 80b9a3c0..cd21444b 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -94,6 +94,39 @@ public: inline bool operator<=(const Path &p) const throw() { return (_addr <= p._addr); } inline bool operator>=(const Path &p) const throw() { return (_addr >= p._addr); } + /** + * Check whether this address is valid for a ZeroTier path + * + * This checks the address type and scope against address types and scopes + * that we currently support for ZeroTier communication. + * + * @param a Address to check + * @return True if address is good for ZeroTier path use + */ + static inline bool isAddressValidForPath(const InetAddress &a) + throw() + { + if ((a.ss_family == AF_INET)||(a.ss_family == AF_INET6)) { + switch(a.ipScope()) { + /* Note: we don't do link-local at the moment. Unfortunately these + * cause several issues. The first is that they usually require a + * device qualifier, which we don't handle yet and can't portably + * push in PUSH_DIRECT_PATHS. The second is that some OSes assign + * these very ephemerally or otherwise strangely. So we'll use + * private, pseudo-private, shared (e.g. carrier grade NAT), or + * global IP addresses. */ + case InetAddress::IP_SCOPE_PRIVATE: + case InetAddress::IP_SCOPE_PSEUDOPRIVATE: + case InetAddress::IP_SCOPE_SHARED: + case InetAddress::IP_SCOPE_GLOBAL: + return true; + default: + return false; + } + } + return false; + } + protected: InetAddress _addr; int _metric; // negative == blacklisted diff --git a/service/OneService.cpp b/service/OneService.cpp index 527ac1b0..bde59d56 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -591,20 +591,8 @@ public: } 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; - } - } + ip.setPort(_port); + _node->addLocalInterfaceAddress(reinterpret_cast(&ip),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL,0); } } ifa = ifa->ifa_next; @@ -637,20 +625,8 @@ public: PIP_ADAPTER_UNICAST_ADDRESS ua = a->FirstUnicastAddress; while (ua) { InetAddress ip(ua->Address.lpSockaddr); - 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; - } - } + ip.setPort(_port); + _node->addLocalInterfaceAddress(reinterpret_cast(&ip),0,ZT1_LOCAL_INTERFACE_ADDRESS_TRUST_NORMAL,0); ua = ua->Next; } } -- cgit v1.2.3