Kaynağa Gözat

Route management now works on Windows, including default route override! 1.1.6 very close!

Adam Ierymenko 9 yıl önce
ebeveyn
işleme
4f237687ce

+ 90 - 0
osdep/ManagedRoute.cpp

@@ -284,6 +284,59 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress
 #ifdef __WINDOWS__ // --------------------------------------------------------
 #define ZT_ROUTING_SUPPORT_FOUND 1
 
+static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &interfaceIndex,const InetAddress &target,const InetAddress &via)
+{
+	MIB_IPFORWARD_ROW2 rtrow;
+	InitializeIpForwardEntry(&rtrow);
+	rtrow.InterfaceLuid.Value = interfaceLuid.Value;
+	rtrow.InterfaceIndex = interfaceIndex;
+	if (target.ss_family == AF_INET) {
+		rtrow.DestinationPrefix.Prefix.si_family = AF_INET;
+		rtrow.DestinationPrefix.Prefix.Ipv4.sin_family = AF_INET;
+		rtrow.DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&target)->sin_addr.S_un.S_addr;
+		if (via.ss_family == AF_INET) {
+			rtrow.NextHop.si_family = AF_INET;
+			rtrow.NextHop.Ipv4.sin_family = AF_INET;
+			rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast<const struct sockaddr_in *>(&via)->sin_addr.S_un.S_addr;
+		}
+	} else if (target.ss_family == AF_INET6) {
+		rtrow.DestinationPrefix.Prefix.si_family = AF_INET6;
+		rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6;
+		memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte,reinterpret_cast<const struct sockaddr_in6 *>(&target)->sin6_addr.u.Byte,16);
+		if (via.ss_family == AF_INET6) {
+			rtrow.NextHop.si_family = AF_INET6;
+			rtrow.NextHop.Ipv6.sin6_family = AF_INET6;
+			memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte,reinterpret_cast<const struct sockaddr_in6 *>(&via)->sin6_addr.u.Byte,16);
+		}
+	} else {
+		return false;
+	}
+	rtrow.DestinationPrefix.PrefixLength = target.netmaskBits();
+	rtrow.SitePrefixLength = rtrow.DestinationPrefix.PrefixLength;
+	rtrow.ValidLifetime = 0xffffffff;
+	rtrow.PreferredLifetime = 0xffffffff;
+	rtrow.Metric = -1;
+	rtrow.Protocol = MIB_IPPROTO_NETMGMT;
+	rtrow.Loopback = FALSE;
+	rtrow.AutoconfigureAddress = FALSE;
+	rtrow.Publish = FALSE;
+	rtrow.Immortal = FALSE;
+	rtrow.Age = 0;
+	rtrow.Origin = NlroManual;
+	if (del) {
+		return (DeleteIpForwardEntry2(&rtrow) == NO_ERROR);
+	} else {
+		NTSTATUS r = CreateIpForwardEntry2(&rtrow);
+		if (r == NO_ERROR) {
+			return true;
+		} else if (r == ERROR_OBJECT_ALREADY_EXISTS) {
+			return (SetIpForwardEntry2(&rtrow) == NO_ERROR);
+		} else {
+			return false;
+		}
+	}
+}
+
 #endif // __WINDOWS__ --------------------------------------------------------
 
 #ifndef ZT_ROUTING_SUPPORT_FOUND
@@ -305,6 +358,14 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress
 
 bool ManagedRoute::sync()
 {
+#ifdef __WINDOWS__
+	NET_LUID interfaceLuid;
+	interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
+	NET_IFINDEX interfaceIndex = -1;
+	if (ConvertInterfaceLuidToIndex(&interfaceLuid,&interfaceIndex) != NO_ERROR)
+		return false;
+#endif
+
 	if ((_target.isDefaultRoute())||((_target.ss_family == AF_INET)&&(_target.netmaskBits() < 32))) {
 		/* In ZeroTier we create two more specific routes for every one route. We
 		 * do this for default routes and IPv4 routes other than /32s. If there
@@ -399,6 +460,12 @@ bool ManagedRoute::sync()
 
 #ifdef __WINDOWS__ // --------------------------------------------------------
 
+		if (!_applied) {
+			_winRoute(false,interfaceLuid,interfaceIndex,leftt,_via);
+			_winRoute(false,interfaceLuid,interfaceIndex,rightt,_via);
+			_applied = true;
+		}
+
 #endif // __WINDOWS__ --------------------------------------------------------
 
 	} else {
@@ -420,10 +487,20 @@ bool ManagedRoute::sync()
 
 #ifdef __LINUX__ // ----------------------------------------------------------
 
+		if (!_applied) {
+			_routeCmd("replace",_target,_via,(_via) ? _device : (const char *)0);
+			_applied = true;
+		}
+
 #endif // __LINUX__ ----------------------------------------------------------
 
 #ifdef __WINDOWS__ // --------------------------------------------------------
 
+		if (!_applied) {
+			_winRoute(false,interfaceLuid,interfaceIndex,_target,_via);
+			_applied = true;
+		}
+
 #endif // __WINDOWS__ --------------------------------------------------------
 
 	}
@@ -433,6 +510,14 @@ bool ManagedRoute::sync()
 
 void ManagedRoute::remove()
 {
+#ifdef __WINDOWS__
+	NET_LUID interfaceLuid;
+	interfaceLuid.Value = (ULONG64)Utils::hexStrToU64(_device); // on Windows we use the hex LUID as the "interface name" for ManagedRoute
+	NET_IFINDEX interfaceIndex = -1;
+	if (ConvertInterfaceLuidToIndex(&interfaceLuid,&interfaceIndex) != NO_ERROR)
+		return;
+#endif
+
 	if (_applied) {
 		if ((_target.isDefaultRoute())||((_target.ss_family == AF_INET)&&(_target.netmaskBits() < 32))) {
 			InetAddress leftt,rightt;
@@ -463,6 +548,9 @@ void ManagedRoute::remove()
 
 #ifdef __WINDOWS__ // --------------------------------------------------------
 
+			_winRoute(true,interfaceLuid,interfaceIndex,leftt,_via);
+			_winRoute(true,interfaceLuid,interfaceIndex,rightt,_via);
+
 #endif // __WINDOWS__ --------------------------------------------------------
 
 		} else {
@@ -485,6 +573,8 @@ void ManagedRoute::remove()
 
 #ifdef __WINDOWS__ // --------------------------------------------------------
 
+			_winRoute(true,interfaceLuid,interfaceIndex,_target,_via);
+
 #endif // __WINDOWS__ --------------------------------------------------------
 
 		}

+ 8 - 0
osdep/WindowsEthernetTap.cpp

@@ -861,6 +861,14 @@ void WindowsEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,
 	_multicastGroups.swap(newGroups);
 }
 
+NET_IFINDEX WindowsEthernetTap::interfaceIndex() const
+{
+	NET_IFINDEX idx = -1;
+	if (ConvertInterfaceLuidToIndex(&_deviceLuid,&idx) == NO_ERROR)
+		return idx;
+	return -1;
+}
+
 void WindowsEthernetTap::threadMain()
 	throw()
 {

+ 1 - 0
osdep/WindowsEthernetTap.hpp

@@ -105,6 +105,7 @@ public:
 	inline const NET_LUID &luid() const { return _deviceLuid; }
 	inline const GUID &guid() const { return _deviceGuid; }
 	inline const std::string &instanceId() const { return _deviceInstanceId; }
+	NET_IFINDEX interfaceIndex() const;
 
 	void threadMain()
 		throw();

+ 7 - 2
service/OneService.cpp

@@ -1051,7 +1051,12 @@ public:
 		}
 
 		if (syncRoutes) {
-			const std::string tapdev(n.tap->deviceName());
+			char tapdev[64];
+#ifdef __WINDOWS__
+			Utils::snprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value);
+#else
+			Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str());
+#endif
 
 			// Nuke applied routes that are no longer in n.config.routes[] and/or are not allowed
 			for(std::list<ManagedRoute>::iterator mr(n.managedRoutes.begin());mr!=n.managedRoutes.end();) {
@@ -1106,7 +1111,7 @@ public:
 
 				// Add and apply new routes
 				n.managedRoutes.push_back(ManagedRoute());
-				if (!n.managedRoutes.back().set(*target,*via,tapdev.c_str()))
+				if (!n.managedRoutes.back().set(*target,*via,tapdev))
 					n.managedRoutes.pop_back();
 			}
 		}