[TCPIP] Read the interface metric from the registry or use the automatic metric feature

- Read the interface metric from the registry.
- Assign an automatic metric to an interface if a registry value is not available.
- Determine the automatic metric from the link speed. The metric for the loopback interface is always 1.
This commit is contained in:
Eric Kohl
2026-03-14 21:10:56 +01:00
parent 606d22d6c0
commit 07d30c679e
5 changed files with 57 additions and 11 deletions

View File

@@ -576,6 +576,7 @@ BOOLEAN ReadIpConfiguration(PIP_INTERFACE Interface)
UNICODE_STRING Netmask = RTL_CONSTANT_STRING(L"SubnetMask");
UNICODE_STRING Gateway = RTL_CONSTANT_STRING(L"DefaultGateway");
UNICODE_STRING EnableDhcp = RTL_CONSTANT_STRING(L"EnableDHCP");
UNICODE_STRING InterfaceMetric = RTL_CONSTANT_STRING(L"InterfaceMetric");
UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\");
UNICODE_STRING TcpipRegistryPath;
UNICODE_STRING RegistryDataU;
@@ -619,6 +620,21 @@ BOOLEAN ReadIpConfiguration(PIP_INTERFACE Interface)
return FALSE;
}
/* Read the InterfaceMetric value */
Interface->Metric = 0;
Status = ZwQueryValueKey(ParameterHandle,
&InterfaceMetric,
KeyValuePartialInformation,
KeyValueInfo,
KeyValueInfoLength,
&Unused);
if (NT_SUCCESS(Status) && KeyValueInfo->DataLength == sizeof(ULONG))
{
Interface->Metric = (UINT)*(PULONG)KeyValueInfo->Data;
if (Interface->Metric > 9999)
Interface->Metric = 9999;
}
/* Read the EnableDHCP entry */
Status = ZwQueryValueKey(ParameterHandle,
&EnableDhcp,
@@ -700,7 +716,7 @@ BOOLEAN ReadIpConfiguration(PIP_INTERFACE Interface)
AddrInitIPv4(&Router, inet_addr(RegistryDataA.Buffer));
if (!AddrIsUnspecified(&Router))
RouterCreateRoute(&DefaultMask, &DefaultMask, &Router, Interface, 1);
RouterCreateRoute(&DefaultMask, &DefaultMask, &Router, Interface);
RtlFreeAnsiString(&RegistryDataA);
}

View File

@@ -156,6 +156,7 @@ typedef struct _IP_INTERFACE {
UINT MinFrameSize; /* Minimum frame size in bytes */
UINT MTU; /* Maximum transmission unit */
UINT Speed; /* Link speed */
UINT Metric; /* Interface metric */
IP_ADDRESS Unicast; /* Unicast address */
IP_ADDRESS PointToPoint; /* Point to point address */
IP_ADDRESS Netmask; /* Netmask */

View File

@@ -34,8 +34,7 @@ PFIB_ENTRY RouterCreateRoute(
PIP_ADDRESS NetworkAddress,
PIP_ADDRESS Netmask,
PIP_ADDRESS RouterAddress,
PIP_INTERFACE Interface,
UINT Metric);
PIP_INTERFACE Interface);
NTSTATUS RouterStartup(
VOID);
@@ -49,4 +48,6 @@ UINT CountFIBs(PIP_INTERFACE IF);
UINT CopyFIBs( PIP_INTERFACE IF, PFIB_ENTRY Target );
UINT ProcessAutoMetric(PIP_INTERFACE Interface);
/* EOF */

View File

@@ -17,7 +17,37 @@
LIST_ENTRY FIBListHead;
KSPIN_LOCK FIBLock;
void RouterDumpRoutes() {
UINT
ProcessAutoMetric(
_In_ PIP_INTERFACE Interface)
{
if (Interface == Loopback)
return 1;
if (Interface->Metric != 0)
return Interface->Metric;
/* Auto metric */
if (Interface->Speed > 2000000000)
return 5;
else if (Interface->Speed > 200000000)
return 10;
else if (Interface->Speed > 80000000)
return 20;
else if (Interface->Speed > 20000000)
return 25;
else if (Interface->Speed > 4000000)
return 30;
else if (Interface->Speed > 500000)
return 40;
else
return 50;
}
VOID
RouterDumpRoutes(VOID)
{
PLIST_ENTRY CurrentEntry;
PLIST_ENTRY NextEntry;
PFIB_ENTRY Current;
@@ -422,16 +452,14 @@ PFIB_ENTRY RouterCreateRoute(
PIP_ADDRESS NetworkAddress,
PIP_ADDRESS Netmask,
PIP_ADDRESS RouterAddress,
PIP_INTERFACE Interface,
UINT Metric)
PIP_INTERFACE Interface)
/*
* FUNCTION: Creates a route with IPv4 addresses as parameters
* ARGUMENTS:
* NetworkAddress = Address of network
* Netmask = Netmask of network
* RouterAddress = Address of router to use
* NTE = Pointer to NTE to use
* Metric = Cost of this route
* Interface = Network interface
* RETURNS:
* Pointer to FIB entry if the route was created, NULL if not.
* The FIB entry references the NTE. The caller is responsible
@@ -475,7 +503,7 @@ PFIB_ENTRY RouterCreateRoute(
return NULL;
}
return RouterAddRoute(NetworkAddress, Netmask, NCE, Metric);
return RouterAddRoute(NetworkAddress, Netmask, NCE, ProcessAutoMetric(Interface));
}

View File

@@ -327,8 +327,8 @@ TDI_STATUS InfoTdiSetRoute(PIP_INTERFACE IF, PVOID Buffer, UINT BufferSize)
if( Route->Type == IP_ROUTE_TYPE_ADD ) { /* Add the route */
TI_DbgPrint(DEBUG_INFO,("Adding route (%s)\n", A2S(&Address)));
if (!RouterCreateRoute( &Address, &Netmask, &Router,
IF, Route->Metric1))
IF->Metric = Route->Metric1;
if (!RouterCreateRoute(&Address, &Netmask, &Router, IF))
return TDI_NO_RESOURCES;
return TDI_SUCCESS;