在支持Windows XP的C中获取和设置默认网关

时间:2011-03-05 12:43:00

标签: c windows winapi winsock

我找到了用于管理ip相关信息的IP Helper接口,但我找不到使用Windows XP支持的接口获取和/或更改给定适配器的网关地址的方法。有什么想法吗?

4 个答案:

答案 0 :(得分:2)

如果你可以使用WMI,那就是Win32_NetworkAdapterConfiguration类。如果您需要普通的旧C API,我发现this(靠近底部的“设置默认网关地址”)。

答案 1 :(得分:1)

GetAdaptersInfo()GetAdaptersAddresses()函数都返回每个适配器的网关信息。

答案 2 :(得分:0)

注意:Win32_NetworkAdapterConfiguration :: SetGateways()将在参数中设置指定的网关,其中将覆盖exisitng网关。

但是: 正在删除 网关 似乎无法正常工作 当使用SetGateways()WMI调用时 - 在我的情况下,调用返回成功,但网关仍然存在。似乎有很多人看过这个(在StringArray中设置NULL字符串或者为StringArray传递NULL没有帮助)。

在我的情况下,我开始使用WMI方式(很可能是因为EnableDHCP()),但也需要实现Luke建议的WINAPI方式来摆脱网关的灾难。非常感谢Luke !!

答案 3 :(得分:-1)

    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}");
        }
    }

上面的代码使用pinvokes在.net中使用iphelper函数,所以只需忘记pinvokes并使用代码作为win32应用程序的参考。

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366363(v=vs.85).aspx

编辑: 您可以使用以下代码获取适配器信息。并在需要使用SetDefaultGateway时使用Index字段。

    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;
    }