2011年2月1日星期二

一个IPHelper API的实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Runtime.InteropServices;

namespace VPNClient
{
    class iphlpapi
    {
        [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 Int32 Context;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_IPFORWARDROW
        {
            public UInt32 dwForwardDest;        //destination IP address.
            public UInt32 dwForwardMask;        //Subnet mask
            public UInt32 dwForwardPolicy;      //conditions for multi-path route. Unused, specify 0.
            public UInt32 dwForwardNextHop;     //IP address of the next hop. Own address?
            public UInt32 dwForwardIfIndex;     //index of interface
            public UInt32 dwForwardType;        //route type
            public UInt32 dwForwardProto;       //routing protocol.
            public UInt32 dwForwardAge;         //age of route.
            public UInt32 dwForwardNextHopAS;   //autonomous system number. 0 if not relevant
            public int dwForwardMetric1;     //-1 if not used (goes for all metrics)
            public int dwForwardMetric2;
            public int dwForwardMetric3;
            public int dwForwardMetric4;
            public int dwForwardMetric5;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct IP_ADAPTER_INFO
        {
            public IntPtr Next;
            public Int32 ComboIndex;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256 + 4)]
            public string AdapterName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128 + 4)]
            public string AdapterDescription;
            public UInt32 AddressLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            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;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_IPFORWARDTABLE
        {
            public int dwNumEntries;            //number of route entries in the table.
            public MIB_IPFORWARDROW[] table;
        }

        [DllImport("iphlpapi.dll", CharSet = CharSet.Ansi)]
        public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int64 pBufOutLen);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int CreateIpForwardEntry(ref MIB_IPFORWARDROW pRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int DeleteIpForwardEntry(ref MIB_IPFORWARDROW pRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int SetIpForwardEntry(ref MIB_IPFORWARDROW pRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        public static extern int GetIpForwardTable(byte[] pIpForwardTable, out int pdwSize, bool bOrder);


        public static int createIpForwardEntry(UInt32 destIPAddress, UInt32 destMask, UInt32 nextHopIPAddress, UInt32 ifIndex,int metric)
        {
            MIB_IPFORWARDROW mifr = new MIB_IPFORWARDROW();
            mifr.dwForwardDest = destIPAddress;
            mifr.dwForwardMask = destMask;
            mifr.dwForwardNextHop = nextHopIPAddress;
            mifr.dwForwardIfIndex = ifIndex;
            mifr.dwForwardPolicy = Convert.ToUInt32(0);
            mifr.dwForwardType = Convert.ToUInt32(3);
            mifr.dwForwardProto = Convert.ToUInt32(3);
            mifr.dwForwardAge = Convert.ToUInt32(0);
            mifr.dwForwardNextHopAS = Convert.ToUInt32(0);
            mifr.dwForwardMetric1 = metric;
            mifr.dwForwardMetric2 = -1;
            mifr.dwForwardMetric3 = -1;
            mifr.dwForwardMetric4 = -1;
            mifr.dwForwardMetric5 = -1;
            return CreateIpForwardEntry(ref mifr);
        }

        public static int deleteIpForwardEntry(UInt32 destIPAddress, UInt32 destMask, UInt32 nextHopIPAddress, UInt32 ifIndex)
        {
            MIB_IPFORWARDROW mifr = new MIB_IPFORWARDROW();
            mifr.dwForwardDest = destIPAddress;
            mifr.dwForwardMask = destMask;
            mifr.dwForwardNextHop = nextHopIPAddress;
            mifr.dwForwardIfIndex = ifIndex;
            mifr.dwForwardPolicy = Convert.ToUInt32(0);
            mifr.dwForwardType = Convert.ToUInt32(3);
            mifr.dwForwardProto = Convert.ToUInt32(3);
            mifr.dwForwardAge = Convert.ToUInt32(0);
            mifr.dwForwardNextHopAS = Convert.ToUInt32(0);
            mifr.dwForwardMetric1 = -1;
            mifr.dwForwardMetric2 = -1;
            mifr.dwForwardMetric3 = -1;
            mifr.dwForwardMetric4 = -1;
            mifr.dwForwardMetric5 = -1;
            return DeleteIpForwardEntry(ref mifr);
        }

        const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
        const int ERROR_BUFFER_OVERFLOW = 111;
        const int MAX_ADAPTER_NAME_LENGTH = 256;
        const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
        const int MIB_IF_TYPE_OTHER = 1;
        const int MIB_IF_TYPE_ETHERNET = 6;
        const int MIB_IF_TYPE_TOKENRING = 9;
        const int MIB_IF_TYPE_FDDI = 15;
        const int MIB_IF_TYPE_PPP = 23;
        const int MIB_IF_TYPE_LOOPBACK = 24;
        const int MIB_IF_TYPE_SLIP = 28;

        /// <summary>
        /// IPAddressToNumber
        /// </summary>
        /// <param name="IPaddress"></param>
        /// <returns></returns>
        public static double IPAddressToNumber(string IPaddress)
        {
            int i;
            string[] arrDec;
            double num = 0;
            if (IPaddress == "")
            {
                return 0;
            }
            else
            {
                arrDec = IPaddress.Split('.');
                for (i = arrDec.Length - 1; i >= 0; i = i - 1)
                {
                    num += ((int.Parse(arrDec[i]) % 256) * Math.Pow(256, (3 - i)));
                }
                return num;
            }
        }

        /// <summary>
        /// GetAdaptersIndex
        /// </summary>
        /// <returns></returns>
        public static string GetAdaptersIndex()
        {
            string result = string.Empty;
            long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
            IntPtr pArray = Marshal.AllocHGlobal(new IntPtr(structSize));
            int ret = GetAdaptersInfo(pArray, ref structSize);

            if (ret == ERROR_BUFFER_OVERFLOW) // ERROR_BUFFER_OVERFLOW == 111
            {
                pArray = Marshal.ReAllocHGlobal(pArray, new IntPtr(structSize));
                ret = GetAdaptersInfo(pArray, ref structSize);
            }

            if (ret == 0)
            {
                IntPtr pEntry = pArray;
                do
                {
                    IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));
                    if (entry.AdapterDescription.IndexOf("PPP") >= 0 || entry.AdapterDescription.IndexOf("SLIP") >= 0 || entry.AdapterDescription.IndexOf("PPTP") >= 0 || entry.AdapterDescription.IndexOf("VPN") >= 0)
                    {
                        result += (result == string.Empty ? string.Empty : "|") + entry.Index.ToString();
                    }
                    pEntry = entry.Next;
                }
                while (pEntry != IntPtr.Zero);
                Marshal.FreeHGlobal(pArray);
                return result;
            }
            else
            {
                Marshal.FreeHGlobal(pArray);
                throw new InvalidOperationException("GetAdaptersInfo failed: " + ret);
            }

        }

        /// <summary>
        /// GetAdapters
        /// </summary>
        public static void GetAdapters()
        {
            long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
            IntPtr pArray = Marshal.AllocHGlobal(new IntPtr(structSize));

            int ret = GetAdaptersInfo(pArray, ref structSize);

            if (ret == ERROR_BUFFER_OVERFLOW) // ERROR_BUFFER_OVERFLOW == 111
            {
                // Buffer was too small, reallocate the correct size for the buffer.
                pArray = Marshal.ReAllocHGlobal(pArray, new IntPtr(structSize));

                ret = GetAdaptersInfo(pArray, ref structSize);
            } // if

            if (ret == 0)
            {
                // Call Succeeded
                IntPtr pEntry = pArray;

                do
                {
                    // Retrieve the adapter info from the memory address
                    IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));

                    // ***Do something with the data HERE!***
                    Console.WriteLine("\n");
                    Console.WriteLine("Index: {0}", entry.Index.ToString());

                    // Adapter Type
                    string tmpString = string.Empty;
                    switch (entry.Type)
                    {
                        case MIB_IF_TYPE_ETHERNET: tmpString = "Ethernet"; break;
                        case MIB_IF_TYPE_TOKENRING: tmpString = "Token Ring"; break;
                        case MIB_IF_TYPE_FDDI: tmpString = "FDDI"; break;
                        case MIB_IF_TYPE_PPP: tmpString = "PPP"; break;
                        case MIB_IF_TYPE_LOOPBACK: tmpString = "Loopback"; break;
                        case MIB_IF_TYPE_SLIP: tmpString = "Slip"; break;
                        default: tmpString = "Other/Unknown"; break;
                    }

                    Console.WriteLine("Adapter Type: {0}", tmpString);
                    Console.WriteLine("Name: {0}", entry.AdapterName);
                    Console.WriteLine("Desc: {0}\n", entry.AdapterDescription);
                    Console.WriteLine("DHCP Enabled: {0}", (entry.DhcpEnabled == 1) ? "Yes" : "No");

                    if (entry.DhcpEnabled == 1)
                    {
                        Console.WriteLine("DHCP Server : {0}", entry.DhcpServer.IpAddress.Address);

                        // Lease Obtained (convert from "time_t" to C# DateTime)
                        DateTime pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseObtained).ToLocalTime();
                        Console.WriteLine("Lease Obtained: {0}", pdatDate.ToString());

                        // Lease Expires (convert from "time_t" to C# DateTime)
                        pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseExpires).ToLocalTime();
                        Console.WriteLine("Lease Expires : {0}\n", pdatDate.ToString());
                    } // if DhcpEnabled

                    Console.WriteLine("IP Address     : {0}", entry.IpAddressList.IpAddress.Address);
                    Console.WriteLine("Subnet Mask    : {0}", entry.IpAddressList.IpMask.Address);
                    Console.WriteLine("Default Gateway: {0}", entry.GatewayList.IpAddress.Address);

                    // MAC Address (data is in a byte[])
                    tmpString = string.Empty;
                    for (int i = 0; i < entry.AddressLength - 1; i++)
                    {
                        tmpString += string.Format("{0:X2}-", entry.Address[i]);
                    }

                    Console.WriteLine("MAC Address    : {0}{1:X2}\n", tmpString, entry.Address[entry.AddressLength - 1]);
                    Console.WriteLine("Has WINS: {0}", entry.HaveWins ? "Yes" : "No");

                    if (entry.HaveWins)
                    {
                        Console.WriteLine("Primary WINS Server  : {0}", entry.PrimaryWinsServer.IpAddress.Address);
                        Console.WriteLine("Secondary WINS Server: {0}", entry.SecondaryWinsServer.IpAddress.Address);
                    }

                    // Get next adapter (if any)
                    pEntry = entry.Next;

                }
                while (pEntry != IntPtr.Zero);
                Marshal.FreeHGlobal(pArray);
            }
            else
            {
                Marshal.FreeHGlobal(pArray);
                throw new InvalidOperationException("GetAdaptersInfo failed: " + ret);
            }

        }
    }
}

没有评论:

发表评论