Getting and Setting the default Gateway in C supporting Windows XP
I have found the IP Helper interfaces for managing ip related information, yet i didnt find a way to get and/or change the Gateway address for a given adapter using interfac开发者_JS百科es supported in Windows XP. Any ideas?
If you can use WMI there is the Win32_NetworkAdapterConfiguration class. If you need plain old C APIs, I found this ("Setting Default Gateway Address" near the bottom).
The GetAdaptersInfo()
and GetAdaptersAddresses()
functions both return Gateway information for each adapter.
Note: Win32_NetworkAdapterConfiguration::SetGateways() will set the gateways you specified in the parameters, where exisitng gateways will be overwritten.
But: Removing the gateway(s) seems not to work when using SetGateways() WMI call - in my case the call returned with success, but the gateway was still present. It seems that there are a lot of people who have seen this (setting up NULL strings in the StringArray or passing NULL for the StringArray did not help).
In my case I began using the WMI way (most likely because of EnableDHCP() ), but also needed to implement the WINAPI way suggested by Luke to get rid of the disaster with the gateways. Much thanks to Luke!!
public enum ForwardType
{
Other = 1,
Invalid = 2,
Direct = 3,
Indirect = 4
}
public enum ForwardProtocol
{
Other = 1,
Local = 2,
NetMGMT = 3,
ICMP = 4,
EGP = 5,
GGP = 6,
Hello = 7,
RIP = 8,
IS_IS = 9,
ES_IS = 10,
CISCO = 11,
BBN = 12,
OSPF = 13,
BGP = 14,
NT_AUTOSTATIC = 10002,
NT_STATIC = 10006,
NT_STATIC_NON_DOD = 10007
}
[StructLayout(LayoutKind.Sequential)]
public struct MIB_IPFORWARDROW
{
public uint dwForwardDest;
public uint dwForwardMask;
public int dwForwardPolicy;
public uint dwForwardNextHop;
public int dwForwardIfIndex;
public ForwardType dwForwardType;
public ForwardProtocol dwForwardProto;
public int dwForwardAge;
public int dwForwardNextHopAS;
public int dwForwardMetric1;
public int dwForwardMetric2;
public int dwForwardMetric3;
public int dwForwardMetric4;
public int dwForwardMetric5;
public static List<MIB_IPFORWARDROW> FromByteArray(byte[] buffer)
{
List<MIB_IPFORWARDROW> ret = new List<MIB_IPFORWARDROW>();
int n =
(buffer[3] << 24) +
(buffer[2] << 16) +
(buffer[1] << 8) +
(buffer[0] << 0);
int offset = sizeof(int);
for (int i = 0; i < n; i++)
{
MIB_IPFORWARDROW map = new MIB_IPFORWARDROW();
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(map));
Marshal.StructureToPtr(map, ptr, false);
Marshal.Copy(buffer, offset, ptr, Marshal.SizeOf(map));
map = (MIB_IPFORWARDROW)Marshal.PtrToStructure(ptr, typeof(MIB_IPFORWARDROW));
Marshal.FreeHGlobal(ptr);
ret.Add(map);
offset += Marshal.SizeOf(map);
}
return ret;
}
}
[DllImport("Iphlpapi.dll", CharSet = CharSet.Auto)]
public static extern int GetIpForwardTable(byte[] pIpForwardTable, ref ulong pdwSize, bool bOrder);
[DllImport("Iphlpapi.dll", CharSet = CharSet.Auto)]
public static extern int DeleteIpForwardEntry(ref MIB_IPFORWARDROW pRoute);
[DllImport("Iphlpapi.dll", CharSet = CharSet.Auto)]
public static extern int SetIpForwardEntry(ref MIB_IPFORWARDROW pRoute);
private static uint IPToUIntR(IPAddress ip)
{
uint ret = 0;
byte[] ipBytes = ip.GetAddressBytes();
ret += (uint)ipBytes[0] << 24;
ret += (uint)ipBytes[1] << 16;
ret += (uint)ipBytes[2] << 8;
ret += (uint)ipBytes[3];
return ret;
}
public static List<MIB_IPFORWARDROW> GetIPForwardTable(int index)
{
List<MIB_IPFORWARDROW> ret = new List<MIB_IPFORWARDROW>();
ulong size = 0;
int err = GetIpForwardTable(null, ref size, false);
byte[] buffer = new byte[size];
err = GetIpForwardTable(buffer, ref size, false);
if (err != 0)
{
throw new System.ComponentModel.Win32Exception(err, $"GetIPForwardTable return with error code {err}");
}
foreach (MIB_IPFORWARDROW mipr in MIB_IPFORWARDROW.FromByteArray(buffer))
{
if (mipr.dwForwardIfIndex != index)
{
continue;
}
ret.Add(mipr);
}
return ret;
}
public static void SetDefaultGateway(int index, string gateway)
{
int err;
int i;
List<MIB_IPFORWARDROW> l = GetIPForwardTable(index);
MIB_IPFORWARDROW mipr = new MIB_IPFORWARDROW();
for (i = 0; i < l.Count; ++i)
{
// 0.0.0.0 default gateway
if (l[i].dwForwardDest != 0)
{
continue;
}
mipr = l[i];
err = DeleteIpForwardEntry(ref mipr);
if (err != 0)
{
throw new System.ComponentModel.Win32Exception(err, $"DeleteIpForwardEntry return with error code {err}");
}
break;
}
mipr.dwForwardNextHop = IPToUIntR(IPAddress.Parse(gateway));
err = SetIpForwardEntry(ref mipr);
if (err != 0)
{
throw new System.ComponentModel.Win32Exception(err, $"DeleteIpForwardEntry return with error code {err}");
}
}
the code above uses pinvokes to use iphelper function in .net, so just forget the pinvokes and use the code as a reference for your win32 application.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366363(v=vs.85).aspx
edit: you can use the code below to obtain adapter information. and use the Index field while you need to use SetDefaultGateway.
const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
const int MAX_ADAPTER_NAME_LENGTH = 256;
const int MAX_ADAPTER_NAME = 128;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADDRESS_STRING
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string Address;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADDR_STRING
{
public IntPtr Next;
public IP_ADDRESS_STRING IpAddress;
public IP_ADDRESS_STRING IpMask;
public ulong Context;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADAPTER_INFO
{
public IntPtr Next;
public Int32 ComboIndex;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_NAME_LENGTH + 4)]
public string AdapterName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ADAPTER_DESCRIPTION_LENGTH + 4)]
public string AdapterDescription;
public UInt32 AddressLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
public byte[] Address;
public Int32 Index;
public UInt32 Type;
public UInt32 DhcpEnabled;
public IntPtr CurrentIpAddress;
public IP_ADDR_STRING IpAddressList;
public IP_ADDR_STRING GatewayList;
public IP_ADDR_STRING DhcpServer;
public bool HaveWins;
public IP_ADDR_STRING PrimaryWinsServer;
public IP_ADDR_STRING SecondaryWinsServer;
public Int32 LeaseObtained;
public Int32 LeaseExpires;
}
[DllImport("iphlpapi.dll", CharSet = CharSet.Ansi)]
static extern int GetAdaptersInfo(byte[] pAdapterInfo, ref ulong pBufOutLen);
public static List<IP_ADAPTER_INFO> GetAllAdapters()
{
List<IP_ADAPTER_INFO> ret = new List<IP_ADAPTER_INFO>();
ulong size = 0;
int err = GetAdaptersInfo(null, ref size);
byte[] buffer = new byte[size];
err = GetAdaptersInfo(buffer, ref size);
if (err != 0)
{
throw new System.ComponentModel.Win32Exception(err, $"GetInterfaceInfo return with error code {err}");
}
GCHandle gc = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr pEntry = gc.AddrOfPinnedObject();
do
{
IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));
ret.Add(entry);
pEntry = entry.Next;
}
while (pEntry != IntPtr.Zero);
gc.Free();
return ret;
}
精彩评论