From 07d30c679ee0144d45f54081ccf07873a2f6c06b Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 14 Mar 2026 21:10:56 +0100 Subject: [PATCH] [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. --- drivers/network/tcpip/datalink/lan.c | 18 +++++++++- drivers/network/tcpip/include/ip.h | 1 + drivers/network/tcpip/include/router.h | 5 +-- drivers/network/tcpip/ip/network/router.c | 40 +++++++++++++++++++---- drivers/network/tcpip/tcpip/ninfo.c | 4 +-- 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/drivers/network/tcpip/datalink/lan.c b/drivers/network/tcpip/datalink/lan.c index e24c8985472..30d5285ca19 100644 --- a/drivers/network/tcpip/datalink/lan.c +++ b/drivers/network/tcpip/datalink/lan.c @@ -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); } diff --git a/drivers/network/tcpip/include/ip.h b/drivers/network/tcpip/include/ip.h index 56e52dede59..93ae7d77b04 100644 --- a/drivers/network/tcpip/include/ip.h +++ b/drivers/network/tcpip/include/ip.h @@ -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 */ diff --git a/drivers/network/tcpip/include/router.h b/drivers/network/tcpip/include/router.h index 6c4f49ab94c..2f41cde661e 100644 --- a/drivers/network/tcpip/include/router.h +++ b/drivers/network/tcpip/include/router.h @@ -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 */ diff --git a/drivers/network/tcpip/ip/network/router.c b/drivers/network/tcpip/ip/network/router.c index e03619f7a11..a92429b037f 100644 --- a/drivers/network/tcpip/ip/network/router.c +++ b/drivers/network/tcpip/ip/network/router.c @@ -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)); } diff --git a/drivers/network/tcpip/tcpip/ninfo.c b/drivers/network/tcpip/tcpip/ninfo.c index 765bb47f9c9..b13b6623990 100644 --- a/drivers/network/tcpip/tcpip/ninfo.c +++ b/drivers/network/tcpip/tcpip/ninfo.c @@ -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;