Introduction
This sample shows how to get the interface metric for an interface with a given interface index, using GetIpInterfaceEntry
with P/Invoke. The forward route metric for CreateIPForwardEntry
on Vista/Server 2008 is then calculated by finding the offset, i.e., gateway cost metric, and adding with the interface metric.
Background
My application which adds new routes to the routing table was working fine until I shifted to Windows 2008. CreateIPForwardEntry
was retuning me an invalid parameter. Then, with some research and Googling, I found that there is actually a breaking API change with CreateIPForwardEntry
, which was not well documented.
On Windows Vista and Windows Server 2008 (WINVER
>= 0x0600), the route metric specified in the dwForwardMetric1
member of the MIB_IPFORWARDROW
structure should be equal to or greater than the metric member of the associated MIB_IPINTERFACE_ROW
structure. An application can retrieve the interface metric by calling the GetIpInterfaceEntry
function. But, I had given 1 for dwForwardMetric1
, which was not working. So, it was required to find the interface metric to calculate the value fordwForwardMetric1
.
Using the code
This sample does not illustrate how to get the interface index for a destination using GetBestInterface
. Currently, my machine’s interface index is used. Also, there is no code included for creating routes using CreateIpForwardEntry
. A WMI query is used to get the gateway metric.
uint interfaceIndex = 9;
MIB_IPINTERFACE_ROW aRow = new MIB_IPINTERFACE_ROW();
aRow.Family = 2;
aRow.InterfaceLuid = 0;
aRow.InterfaceIndex = interfaceIndex;
uint errorCode = GetIpInterfaceEntry(ref aRow);
if (errorCode != 0)
{
throw new Exception("some error");
}
uint forwardMetric = aRow.Metric;
ManagementObjectSearcher query =
new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration" +
" WHERE IPEnabled = 'TRUE' and InterfaceIndex='" +
interfaceIndex.ToString() + "'");
ManagementObjectCollection queryCollection = query.Get();
foreach (ManagementObject tempMObj in queryCollection)
{
UInt16[] getwayCostMetric = tempMObj["GatewayCostMetric"] as UInt16[];
if (getwayCostMetric != null && getwayCostMetric.Length > 0)
{
forwardMetric += getwayCostMetric[0];
}
}
Points of interest
The GatewayCostMetric
or the offset we are calculating will not be available for a network interface with no default gateway configured.
Also, I had some problem initially in marshalling the MIB_IPINTERFACE_ROW
structure because strangely, NL_INTERFACE_OFFLOAD_ROD
described in MSDN is different from what is declared in nldef.h.