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.
This commit is contained in:
Travis LaDuke 2021-12-13 14:23:31 -08:00 committed by Sean OMeara
commit 66a87612b0
2 changed files with 9 additions and 1 deletions

View file

@ -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<const struct sockaddr_in *>(&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<const struct sockaddr_in *>(&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<const struct sockaddr_in6 *>(&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<const struct sockaddr_in6 *>(&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;

View file

@ -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);
}