Browse Source

Unix side of local interface address awareness for GitHub issue #180.

Adam Ierymenko 10 years ago
parent
commit
a87cd2d094
3 changed files with 76 additions and 2 deletions
  1. 7 1
      node/InetAddress.cpp
  2. 0 1
      node/Peer.cpp
  3. 69 0
      service/OneService.cpp

+ 7 - 1
node/InetAddress.cpp

@@ -91,7 +91,13 @@ InetAddress::IpScope InetAddress::ipScope() const
 			const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
 			const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
 			if ((ip[0] & 0xf0) == 0xf0) {
 			if ((ip[0] & 0xf0) == 0xf0) {
 				if (ip[0] == 0xff) return IP_SCOPE_MULTICAST;                              // ff00::/8
 				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
 				if ((ip[0] & 0xfe) == 0xfc) return IP_SCOPE_PRIVATE;                       // fc00::/7
 			}
 			}
 			unsigned int k = 0;
 			unsigned int k = 0;

+ 0 - 1
node/Peer.cpp

@@ -214,7 +214,6 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,const std::vector<Path>
 		_lastDirectPathPush = now;
 		_lastDirectPathPush = now;
 
 
 		TRACE("pushing %u direct paths to %s",(unsigned int)dps.size(),_id.address().toString().c_str());
 		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<Path>::const_iterator p(dps.begin());
 		std::vector<Path>::const_iterator p(dps.begin());
 		while (p != dps.end()) {
 		while (p != dps.end()) {

+ 69 - 0
service/OneService.cpp

@@ -78,8 +78,10 @@ class SqliteNetworkController;
 #include <ShlObj.h>
 #include <ShlObj.h>
 #else
 #else
 #include <sys/types.h>
 #include <sys/types.h>
+#include <sys/socket.h>
 #include <sys/wait.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #include <unistd.h>
+#include <ifaddrs.h>
 #endif
 #endif
 
 
 // Include the right tap device driver for this platform -- add new platforms here
 // 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
 // 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
 #define ZT1_TCP_FALLBACK_AFTER 60000
 
 
+// How often to check for local interface addresses
+#define ZT1_LOCAL_INTERFACE_CHECK_INTERVAL 300000
+
 namespace ZeroTier {
 namespace ZeroTier {
 
 
 namespace {
 namespace {
@@ -405,6 +410,7 @@ public:
 		_nextBackgroundTaskDeadline(0),
 		_nextBackgroundTaskDeadline(0),
 		_tcpFallbackTunnel((TcpConnection *)0),
 		_tcpFallbackTunnel((TcpConnection *)0),
 		_termReason(ONE_STILL_RUNNING),
 		_termReason(ONE_STILL_RUNNING),
+		_port(port),
 		_run(true)
 		_run(true)
 	{
 	{
 		struct sockaddr_in in4;
 		struct sockaddr_in in4;
@@ -501,6 +507,7 @@ public:
 			_lastRestart = clockShouldBe;
 			_lastRestart = clockShouldBe;
 			uint64_t lastTapMulticastGroupCheck = 0;
 			uint64_t lastTapMulticastGroupCheck = 0;
 			uint64_t lastTcpFallbackResolve = 0;
 			uint64_t lastTcpFallbackResolve = 0;
+			uint64_t lastLocalInterfaceAddressCheck = 0;
 #ifdef ZT_AUTO_UPDATE
 #ifdef ZT_AUTO_UPDATE
 			uint64_t lastSoftwareUpdateCheck = 0;
 			uint64_t lastSoftwareUpdateCheck = 0;
 #endif // ZT_AUTO_UPDATE
 #endif // ZT_AUTO_UPDATE
@@ -554,6 +561,66 @@ public:
 					}
 					}
 				}
 				}
 
 
+				if ((now - lastLocalInterfaceAddressCheck) >= ZT1_LOCAL_INTERFACE_CHECK_INTERVAL) {
+					lastLocalInterfaceAddressCheck = now;
+
+#ifdef __UNIX_LIKE__
+					std::vector<std::string> 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<std::string>::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<const struct sockaddr_storage *>(&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<NET_LUID> 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;
 				const unsigned long delay = (dl > now) ? (unsigned long)(dl - now) : 100;
 				clockShouldBe = now + (uint64_t)delay;
 				clockShouldBe = now + (uint64_t)delay;
 				_phy.poll(delay);
 				_phy.poll(delay);
@@ -1158,6 +1225,8 @@ private:
 	std::string _fatalErrorMessage;
 	std::string _fatalErrorMessage;
 	Mutex _termReason_m;
 	Mutex _termReason_m;
 
 
+	unsigned int _port;
+
 	bool _run;
 	bool _run;
 	Mutex _run_m;
 	Mutex _run_m;
 };
 };