summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@zerotier.com>2016-06-21 13:54:03 -0700
committerAdam Ierymenko <adam.ierymenko@zerotier.com>2016-06-21 13:54:03 -0700
commit4f237687ce4c0b7085733d808829fd4b83cf3483 (patch)
tree5b4a799e4ba656d22a06735032550375fd0f3d48
parent5b2d2efb45a856968c7298b00b6cbe08feb66054 (diff)
downloadinfinitytier-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.cpp90
-rw-r--r--osdep/WindowsEthernetTap.cpp8
-rw-r--r--osdep/WindowsEthernetTap.hpp1
-rw-r--r--service/OneService.cpp9
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();
}
}