Using GetIpInterfaceEntry with P/Invoke for getting an interface metric






4.31/5 (4 votes)
Using GetIpInterfaceEntry to get an interface metric, and then calculating dwForwardMetric1 for creating routes in Vista/Windows Server 2008.
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.
//From GetBestInterface for a destination
uint interfaceIndex = 9;
//So we query for the interface with
//the interface index got from GetBestInterface
MIB_IPINTERFACE_ROW aRow = new MIB_IPINTERFACE_ROW();
aRow.Family = 2;
aRow.InterfaceLuid = 0;
aRow.InterfaceIndex = interfaceIndex;
//GetIpInterfaceEntry is available in Vista/2008 server or higher
uint errorCode = GetIpInterfaceEntry(ref aRow);
if (errorCode != 0)
{
throw new Exception("some error");
}
uint forwardMetric = aRow.Metric;
//Now we calculate the offset metric from
//the Gateway configured for this interface
ManagementObjectSearcher query =
new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration" +
" WHERE IPEnabled = 'TRUE' and InterfaceIndex='" +
interfaceIndex.ToString() + "'");
ManagementObjectCollection queryCollection = query.Get();
foreach (ManagementObject tempMObj in queryCollection)
{
//Then we get the GatewayCostMetric and add it with Interface Metric;
UInt16[] getwayCostMetric = tempMObj["GatewayCostMetric"] as UInt16[];
//if not default gateway configured then this will be null
if (getwayCostMetric != null && getwayCostMetric.Length > 0)
{
//we interface metic and offset
forwardMetric += getwayCostMetric[0];
}
}
//This forwardMetric can be used for Creating routes
//using CreateIPForwardEntry in Vista/ Windows Server 2008
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.