From 66a87612b03709c332195ca574e089fa239f5cad Mon Sep 17 00:00:00 2001 From: Travis LaDuke Date: Mon, 13 Dec 2021 14:23:31 -0800 Subject: [PATCH] Windows interface and route metrics 5 is the lowest metrics an interface will get based on Windows Automatic Metrics as far as I know. https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/automatic-metric-for-ipv4-routes If we set our metric to 3, there's a chance Windows will use it for broadcast traffic, and things like game discovery will work. If the user doesn't want that, they can leave the zerotier network or manually set the metric on their physical interface to < 3. For routes with "via"'s we put the metric high, in case it overlaps with a physical route to the same subnet. These could be plumbed through and set via the controller or local.conf someday, istead of being hardcoded magic numbers. --- osdep/ManagedRoute.cpp | 6 +++++- osdep/WindowsEthernetTap.cpp | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osdep/ManagedRoute.cpp b/osdep/ManagedRoute.cpp index a8f996839..eab889343 100644 --- a/osdep/ManagedRoute.cpp +++ b/osdep/ManagedRoute.cpp @@ -292,14 +292,17 @@ static void _routeCmd(const char *op,const InetAddress &target,const InetAddress static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX &interfaceIndex,const InetAddress &target,const InetAddress &via) { MIB_IPFORWARD_ROW2 rtrow; + const int ROUTE_METRIC = 5000; InitializeIpForwardEntry(&rtrow); rtrow.InterfaceLuid.Value = interfaceLuid.Value; rtrow.InterfaceIndex = interfaceIndex; + rtrow.Metric = -1; 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(&target)->sin_addr.S_un.S_addr; if (via.ss_family == AF_INET) { + rtrow.Metric = ROUTE_METRIC; rtrow.NextHop.si_family = AF_INET; rtrow.NextHop.Ipv4.sin_family = AF_INET; rtrow.NextHop.Ipv4.sin_addr.S_un.S_addr = reinterpret_cast(&via)->sin_addr.S_un.S_addr; @@ -309,6 +312,7 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX & rtrow.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6; memcpy(rtrow.DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte,reinterpret_cast(&target)->sin6_addr.u.Byte,16); if (via.ss_family == AF_INET6) { + rtrow.Metric = ROUTE_METRIC; rtrow.NextHop.si_family = AF_INET6; rtrow.NextHop.Ipv6.sin6_family = AF_INET6; memcpy(rtrow.NextHop.Ipv6.sin6_addr.u.Byte,reinterpret_cast(&via)->sin6_addr.u.Byte,16); @@ -320,7 +324,7 @@ static bool _winRoute(bool del,const NET_LUID &interfaceLuid,const NET_IFINDEX & 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; diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp index c0dcbd98f..b21817e91 100644 --- a/osdep/WindowsEthernetTap.cpp +++ b/osdep/WindowsEthernetTap.cpp @@ -568,6 +568,10 @@ WindowsEthernetTap::WindowsEthernetTap( if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) { DWORD enable = 0; RegSetKeyValueA(tcpIpInterfaces,_netCfgInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable)); + + DWORD metric = 3; + RegSetKeyValueA(tcpIpInterfaces, _netCfgInstanceId.c_str(), "InterfaceMetric", REG_DWORD, &metric, sizeof(metric)); + RegCloseKey(tcpIpInterfaces); }