diff options
author | Adam Ierymenko <adam.ierymenko@zerotier.com> | 2016-06-21 13:54:03 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@zerotier.com> | 2016-06-21 13:54:03 -0700 |
commit | 4f237687ce4c0b7085733d808829fd4b83cf3483 (patch) | |
tree | 5b4a799e4ba656d22a06735032550375fd0f3d48 | |
parent | 5b2d2efb45a856968c7298b00b6cbe08feb66054 (diff) | |
download | infinitytier-4f237687ce4c0b7085733d808829fd4b83cf3483.tar.gz infinitytier-4f237687ce4c0b7085733d808829fd4b83cf3483.zip |
Route management now works on Windows, including default route override! 1.1.6 very close!
-rw-r--r-- | osdep/ManagedRoute.cpp | 90 | ||||
-rw-r--r-- | osdep/WindowsEthernetTap.cpp | 8 | ||||
-rw-r--r-- | osdep/WindowsEthernetTap.hpp | 1 | ||||
-rw-r--r-- | service/OneService.cpp | 9 |
4 files changed, 106 insertions, 2 deletions
diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index 6bfb537d..aee01954 100644 --- a/osdep/ManagedRoute.cpp +++ b/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__ -------------------------------------------------------- } diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index d60c0d54..7e1a5a19 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/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() { diff --git a/osdep/WindowsEthernetTap.hpp b/osdep/WindowsEthernetTap.hpp index 54741262..0bbb17d8 100644 --- a/osdep/WindowsEthernetTap.hpp +++ b/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(); diff --git a/service/OneService.cpp b/service/OneService.cpp index 0825705f..8b27ba49 100644 --- a/service/OneService.cpp +++ b/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(); } } |