C#操作静态路由表(增、删、改、查、遍历)

作者: 小古 分类: C# NET技术 发布时间: 2016-11-26 ė10920 次浏览 60 条评论

C#操作静态路由表,通过Windows原生API进行操作(效率比通过CMD操作的高很多),支持增、删、改、查、遍历

使用的是Iphlpapi.dll库,这个库里面还有很多很好用的API,有兴趣的童鞋自行研究吧,这里只用了路由表相关的API

这个,那个,好像没啥好说了,接下来直接看代码吧

等等,差点忘了,如果有童鞋需要需要Demo,那么请下载“C#通过DotRas实现完美控制VPN和PPPoE(ADSL)”这篇博文里的Demo(里面也使用了路由表操作)

好了,下面看代码

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

namespace RBTI.Toolbox.RasConnect.Network
{
    static class RouteTableManager
    {
        public enum MIB_IPFORWARD_TYPE : uint
        {
            /// <summary>
            /// Some other type not specified in RFC 1354.
            /// </summary>
            MIB_IPROUTE_TYPE_OTHER = 1,
            /// <summary>
            /// An invalid route. This value can result from a route added by an ICMP redirect.
            /// </summary>
            MIB_IPROUTE_TYPE_INVALID = 2,
            /// <summary>
            /// A local route where the next hop is the final destination (a local interface).
            /// </summary>
            MIB_IPROUTE_TYPE_DIRECT = 3,
            /// <summary>
            /// The remote route where the next hop is not the final destination (a remote destination).
            /// </summary>
            MIB_IPROUTE_TYPE_INDIRECT = 4
        }

        public enum MIB_IPPROTO : uint
        {
            /// <summary>
            /// Some other protocol not specified in RFC 1354.
            /// </summary>
            MIB_IPPROTO_OTHER = 1,
            /// <summary>
            /// A local interface.
            /// </summary>
            MIB_IPPROTO_LOCAL = 2,
            /// <summary>
            /// A static route. 
            /// This value is used to identify route information for IP routing
            /// set through network management such as the Dynamic Host Configuration
            /// Protocol (DCHP), the Simple Network Management Protocol (SNMP),
            /// or by calls to the CreateIpForwardEntry, DeleteIpForwardEntry,
            /// or SetIpForwardEntry functions.
            /// </summary>
            MIB_IPPROTO_NETMGMT = 3,
            /// <summary>
            /// The result of ICMP redirect.
            /// </summary>
            MIB_IPPROTO_ICMP = 4,
            /// <summary>
            /// The Exterior Gateway Protocol (EGP), a dynamic routing protocol.
            /// </summary>
            MIB_IPPROTO_EGP = 5,
            /// <summary>
            /// The Gateway-to-Gateway Protocol (GGP), a dynamic routing protocol.
            /// </summary>
            MIB_IPPROTO_GGP = 6,
            /// <summary>
            /// The Hellospeak protocol, a dynamic routing protocol. This is a
            /// historical entry no longer in use and was an early routing protocol
            /// used by the original ARPANET routers that ran special software
            /// called the Fuzzball routing protocol, sometimes called Hellospeak,
            /// as described in RFC 891 and RFC 1305. For more information,
            /// see http://www.ietf.org/rfc/rfc891.txt and http://www.ietf.org/rfc/rfc1305.txt.
            /// </summary>
            MIB_IPPROTO_HELLO = 7,
            /// <summary>
            /// The Berkeley Routing Information Protocol (RIP) or RIP-II, a dynamic routing protocol.
            /// </summary>
            MIB_IPPROTO_RIP = 8,
            /// <summary>
            /// The Intermediate System-to-Intermediate System (IS-IS) protocol,
            /// a dynamic routing protocol. The IS-IS protocol was developed for
            /// use in the Open Systems Interconnection (OSI) protocol suite.
            /// </summary>
            MIB_IPPROTO_IS_IS = 9,
            /// <summary>
            /// The End System-to-Intermediate System (ES-IS) protocol, a dynamic
            /// routing protocol. The ES-IS protocol was developed for use in the
            /// Open Systems Interconnection (OSI) protocol suite.
            /// </summary>
            MIB_IPPROTO_ES_IS = 10,
            /// <summary>
            /// The Cisco Interior Gateway Routing Protocol (IGRP), a dynamic routing protocol.
            /// </summary>
            MIB_IPPROTO_CISCO = 11,
            /// <summary>
            /// The Bolt, Beranek, and Newman (BBN) Interior Gateway Protocol
            /// (IGP) that used the Shortest Path First (SPF) algorithm. This
            /// was an early dynamic routing protocol.
            /// </summary>
            MIB_IPPROTO_BBN = 12,
            /// <summary>
            /// The Open Shortest Path First (OSPF) protocol, a dynamic routing protocol.
            /// </summary>
            MIB_IPPROTO_OSPF = 13,
            /// <summary>
            /// The Border Gateway Protocol (BGP), a dynamic routing protocol.
            /// </summary>
            MIB_IPPROTO_BGP = 14,
            /// <summary>
            /// A Windows specific entry added originally by a routing protocol, but which is now static.
            /// </summary>
            MIB_IPPROTO_NT_AUTOSTATIC = 10002,
            /// <summary>
            /// A Windows specific entry added as a static route from the routing user interface or a routing command.
            /// </summary>
            MIB_IPPROTO_NT_STATIC = 10006,
            /// <summary>
            /// A Windows specific entry added as a static route from the routing
            /// user interface or a routing command, except these routes do not cause Dial On Demand (DOD).
            /// </summary>
            MIB_IPPROTO_NT_STATIC_NON_DOD = 10007
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_IPFORWARDROW
        {
            public uint dwForwardDest;        //destination IP address.
            public uint dwForwardMask;        //Subnet mask
            public uint dwForwardPolicy;      //conditions for multi-path route. Unused, specify 0.
            public uint dwForwardNextHop;     //IP address of the next hop. Own address?
            public uint dwForwardIfIndex;     //index of interface
            public MIB_IPFORWARD_TYPE dwForwardType;        //route type
            public MIB_IPPROTO dwForwardProto;       //routing protocol.
            public uint dwForwardAge;         //age of route.
            public uint 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)]
        public struct MIB_IPINTERFACE_ROW
        {
            public uint Family;
            public ulong InterfaceLuid;
            public uint InterfaceIndex;
            public uint MaxReassemblySize;
            public ulong InterfaceIdentifier;
            public uint MinRouterAdvertisementInterval;
            public uint MaxRouterAdvertisementInterval;
            public byte AdvertisingEnabled;
            public byte ForwardingEnabled;
            public byte WeakHostSend;
            public byte WeakHostReceive;
            public byte UseAutomaticMetric;
            public byte UseNeighborUnreachabilityDetection;
            public byte ManagedAddressConfigurationSupported;
            public byte OtherStatefulConfigurationSupported;
            public byte AdvertiseDefaultRoute;
            public uint RouterDiscoveryBehavior;
            public uint DadTransmits;
            public uint BaseReachableTime;
            public uint RetransmitTime;
            public uint PathMtuDiscoveryTimeout;
            public uint LinkLocalAddressBehavior;
            public uint LinkLocalAddressTimeout;
            public uint ZoneIndice0, ZoneIndice1, ZoneIndice2, ZoneIndice3, ZoneIndice4, ZoneIndice5, ZoneIndice6, ZoneIndice7,
             ZoneIndice8, ZoneIndice9, ZoneIndice10, ZoneIndice11, ZoneIndice12, ZoneIndice13, ZoneIndice14, ZoneIndice15;
            public uint SitePrefixLength;
            public uint Metric;
            public uint NlMtu;
            public byte Connected;
            public byte SupportsWakeUpPatterns;
            public byte SupportsNeighborDiscovery;
            public byte SupportsRouterDiscovery;
            public uint ReachableTime;
            public byte TransmitOffload;
            public byte ReceiveOffload;
            public byte DisableDefaultRoutes;
        }

        [StructLayout(LayoutKind.Sequential)]
        private unsafe struct MIB_IPFORWARDTABLE
        {
            /// <summary>
            /// number of route entriesin the table.
            /// </summary>
            public int dwNumEntries;
            public MIB_IPFORWARDROW table;
        }

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

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

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

        [DllImport("Iphlpapi.dll")]
        private static extern int GetIpInterfaceEntry(ref MIB_IPINTERFACE_ROW row);

        [DllImport("iphlpapi.dll", CharSet = CharSet.Auto)]
        private static extern int GetBestInterface(uint DestAddr, out uint BestIfIndex);
        
        [DllImport("Iphlpapi.dll")]
        private static extern int GetBestRoute(uint dwDestAddr, uint dwSourceAddr, out MIB_IPFORWARDROW pBestRoute);

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        private unsafe static extern int GetIpForwardTable(MIB_IPFORWARDTABLE* pIpForwardTable, ref int pdwSize, bool bOrder);

        [DllImport("Kernel32.dll")]
        private extern static int FormatMessage(int flag, ref IntPtr source, int msgid, int langid, ref string buf, int size, ref IntPtr args);

        /// <summary>
        /// 获取错误信息
        /// </summary>
        /// <param name="errCode"></param>
        /// <returns></returns>
        public static string GetErrMsg(int errCode)
        {
            IntPtr tempptr = IntPtr.Zero;
            string msg = null;
            FormatMessage(0x1300, ref tempptr, errCode, 0, ref msg, 255, ref tempptr);
            return msg;
        }

        /// <summary>
        /// 获取路由表
        /// </summary>
        /// <param name="ipForwardTable"></param>
        /// <returns></returns>
        public unsafe static int GetIpForwardTable(out IPForwardRow[] ipForwardTable)
        {
            int res = 0, size = 0;
            size = Marshal.SizeOf(typeof(MIB_IPFORWARDROW));
            MIB_IPFORWARDTABLE* table = (MIB_IPFORWARDTABLE*)Marshal.AllocHGlobal(size);

            res = GetIpForwardTable(table, ref size, true);
            if (res == 0x7A)
            {
                table = (MIB_IPFORWARDTABLE*)Marshal.ReAllocHGlobal((IntPtr)table, (IntPtr)size);
                res = GetIpForwardTable(table, ref size, true);
            }

            if (res == 0)
            {
                ipForwardTable = new IPForwardRow[(*table).dwNumEntries];
                for (int i = 0; i < ipForwardTable.Length; i++)
                {
                    ipForwardTable[i] = new IPForwardRow((&(*table).table)[i]);
                }
            }
            else
                ipForwardTable = null;

            Marshal.FreeHGlobal((IntPtr)table);


            return res;
        }

        /// <summary>
        /// 获取基础路由
        /// </summary>
        /// <param name="destAddr"></param>
        /// <param name="sourceAddr"></param>
        /// <param name="bestRoute"></param>
        /// <returns></returns>
        public static int GetBestRoute(IPAddress destAddr, IPAddress sourceAddr, out IPForwardRow bestRoute)
        {
            MIB_IPFORWARDROW pBestRoute;
            var res = GetBestRoute(IpToUint(destAddr), IpToUint(sourceAddr), out pBestRoute);
            bestRoute = new IPForwardRow(pBestRoute);
            return res;
        }

        /// <summary>
        /// 获取基础接口
        /// </summary>
        /// <param name="destAddr"></param>
        /// <param name="bestIfIndex"></param>
        /// <returns></returns>
        public static int GetBestInterface(IPAddress destAddr, out uint bestIfIndex)
        {
            return GetBestInterface(IpToUint(destAddr), out bestIfIndex);
        }

        /// <summary>
        /// 获取IP接口信息
        /// </summary>
        /// <param name="interfaceIndex"></param>
        /// <param name="row"></param>
        /// <returns></returns>
        public static int GetIpInterfaceEntry(uint interfaceIndex, out MIB_IPINTERFACE_ROW row)
        {
            row = new MIB_IPINTERFACE_ROW();
            row.Family = 2;
            //row.InterfaceLuid = 0;
            row.InterfaceIndex = interfaceIndex;
            return GetIpInterfaceEntry(ref row);
        }

        /// <summary>
        /// 获取单条路由信息
        /// </summary>
        /// <param name="destAddr"></param>
        /// <param name="nextHop"></param>
        /// <param name="route"></param>
        /// <returns></returns>
        public unsafe static int GetIpForwardEntry(IPAddress destAddr, IPAddress nextHop, out IPForwardRow route)
        {
            route = null;

            IPForwardRow[] ipForwardTable;
            var res = GetIpForwardTable(out ipForwardTable);

            if (res == 0)
            {
                for (int i = 0; i < ipForwardTable.Length; i++)
                {
                    if (ipForwardTable[i].Dest.Equals(destAddr) && ipForwardTable[i].NextHop.Equals(nextHop))
                    {
                        route = ipForwardTable[i];
                        break;
                    }
                }
            }

            return res;
        }

        /// <summary>
        /// 获取单条路由信息
        /// </summary>
        /// <param name="destAddr"></param>
        /// <param name="route"></param>
        /// <returns></returns>
        public unsafe static int GetIpForwardEntry(IPAddress destAddr, out IPForwardRow route)
        {
            route = null;

            IPForwardRow[] ipForwardTable;
            var res = GetIpForwardTable(out ipForwardTable);

            if (res == 0)
            {
                for (int i = 0; i < ipForwardTable.Length; i++)
                {
                    if (ipForwardTable[i].Dest.Equals(destAddr))
                    {
                        route = ipForwardTable[i];
                        break;
                    }
                }
            }

            return res;
        }

        /// <summary>
        /// 创建路由
        /// </summary>
        /// <param name="route"></param>
        /// <returns></returns>
        public static int CreateIpForwardEntry(IPForwardRow route)
        {
            return CreateIpForwardEntry(route.GetBaseStruct());
        }

        /// <summary>
        /// 创建路由
        /// </summary>
        /// <param name="dest"></param>
        /// <param name="mask"></param>
        /// <param name="nextHop"></param>
        /// <param name="ifIndex"></param>
        /// <param name="metric"></param>
        /// <returns></returns>
        public static int CreateIpForwardEntry(IPAddress dest, IPAddress mask, IPAddress nextHop, uint ifIndex, int metric = 1)
        {
            IPForwardRow route = new IPForwardRow()
            {
                Dest = dest,
                Mask = mask,
                NextHop = nextHop,
                IfIndex = ifIndex,
                Metric = metric,
                Policy = 0,
                Type = MIB_IPFORWARD_TYPE.MIB_IPROUTE_TYPE_DIRECT,
                Proto = MIB_IPPROTO.MIB_IPPROTO_NETMGMT,
                Age = 0,
                NextHopAS = 0
            };

            OperatingSystem os = Environment.OSVersion;
            if (os.Platform == PlatformID.Win32NT && os.Version.Major >= 6)
            {
                MIB_IPINTERFACE_ROW row;
                int res = GetIpInterfaceEntry(ifIndex, out row);
                if (res != 0)
                    return res;
                route.Metric = (int)row.Metric;
            }

            return CreateIpForwardEntry(route);
        }

        /// <summary>
        /// 创建路由
        /// </summary>
        /// <param name="dest"></param>
        /// <param name="mask"></param>
        /// <param name="nextHop"></param>
        /// <param name="metric"></param>
        /// <returns></returns>
        public static int CreateIpForwardEntry(IPAddress dest, IPAddress mask, IPAddress nextHop, int metric = 1)
        {
            uint bestIfIndex;
            int res = GetBestInterface(nextHop, out bestIfIndex);
            if (res != 0)
                return res;

            return CreateIpForwardEntry(dest, mask, nextHop, bestIfIndex, metric);
        }

        /// <summary>
        /// 创建路由
        /// </summary>
        /// <param name="dest"></param>
        /// <param name="nextHop"></param>
        /// <param name="metric"></param>
        /// <returns></returns>
        public static int CreateIpForwardEntry(IPAddress dest, IPAddress nextHop, int metric = 1)
        {
            return CreateIpForwardEntry(dest, IPAddress.Parse("255.255.255.255"), nextHop, metric);
        }

        /// <summary>
        /// [不推荐使用]修改路由
        /// 仅用于修改网关和跃点数
        /// </summary>
        /// <param name="route"></param>
        /// <returns></returns>
        public static int SetIpForwardEntry(IPForwardRow route)
        {
            return SetIpForwardEntry(route.GetBaseStruct());
        }

        /// <summary>
        /// 删除路由
        /// </summary>
        /// <param name="route"></param>
        /// <returns></returns>
        public static int DeleteIpForwardEntry(IPForwardRow route)
        {
            return DeleteIpForwardEntry(route.GetBaseStruct());
        }

        /// <summary>
        /// 删除路由
        /// </summary>
        /// <param name="destAddr"></param>
        /// <param name="nextHop"></param>
        /// <returns></returns>
        public static int DeleteIpForwardEntry(IPAddress destAddr, IPAddress nextHop)
        {
            IPForwardRow route;
            int res = GetIpForwardEntry(destAddr, nextHop, out route);
            if (res != 0)
                return res;
            return DeleteIpForwardEntry(route);
        }

        /// <summary>
        /// 删除路由
        /// </summary>
        /// <param name="destAddr"></param>
        /// <returns></returns>
        public static int DeleteIpForwardEntry(IPAddress destAddr)
        {
            IPForwardRow route;
            int res = GetIpForwardEntry(destAddr, out route);
            if (res != 0)
                return res;
            return DeleteIpForwardEntry(route);
        }

        /// <summary>
        /// IPAdderss转uint
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <returns></returns>
        public static uint IpToUint(IPAddress ipAddress)
        {
            string[] startIP = ipAddress.ToString().Split('.');

            uint U = uint.Parse(startIP[3]) << 24;
            U += uint.Parse(startIP[2]) << 16;
            U += uint.Parse(startIP[1]) << 8;
            U += uint.Parse(startIP[0]);
            return U;
        }

        /// <summary>
        /// uint转IPAddress
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static IPAddress UintToIp(uint ip)
        {
            string ipStr = $"{ip & 0xff}.{(ip >> 8) & 0xff}.{(ip >> 16) & 0xff}.{(ip >> 24) & 0xff}";
            return IPAddress.Parse(ipStr);
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;

namespace RBTI.Toolbox.RasConnect.Network
{
    class IPForwardRow
    {
        /// <summary>
        /// destination IP address.
        /// </summary>
        public IPAddress Dest { get; set; }
        /// <summary>
        /// Subnet mask
        /// </summary>
        public IPAddress Mask { get; set; }
        /// <summary>
        /// conditions for multi-path route. Unused, specify 0.
        /// </summary>
        public uint Policy { get; set; }
        /// <summary>
        /// IP address of the next hop. Own address?
        /// </summary>
        public IPAddress NextHop { get; set; }
        /// <summary>
        /// index of interface
        /// </summary>
        public uint IfIndex { get; set; }
        /// <summary>
        /// route type
        /// </summary>
        public RouteTableManager.MIB_IPFORWARD_TYPE Type { get; set; }
        /// <summary>
        /// routing protocol.
        /// </summary>
        public RouteTableManager.MIB_IPPROTO Proto { get; set; }
        /// <summary>
        /// age of route.
        /// </summary>
        public uint Age { get; set; }
        /// <summary>
        /// autonomous system number. 0 if not relevant
        /// </summary>
        public uint NextHopAS { get; set; }
        /// <summary>
        /// -1 if not used (goes for all metrics)
        /// </summary>
        public int Metric { get; set; }

        public IPForwardRow()
        {

        }

        public IPForwardRow(RouteTableManager.MIB_IPFORWARDROW baseStruct)
        {
            Dest = RouteTableManager.UintToIp(baseStruct.dwForwardDest);
            Mask = RouteTableManager.UintToIp(baseStruct.dwForwardMask);
            Policy = baseStruct.dwForwardPolicy;
            NextHop = RouteTableManager.UintToIp(baseStruct.dwForwardNextHop);
            IfIndex = baseStruct.dwForwardIfIndex;
            Type = baseStruct.dwForwardType;
            Proto = baseStruct.dwForwardProto;
            Age = baseStruct.dwForwardAge;
            NextHopAS = baseStruct.dwForwardNextHopAS;
            Metric = baseStruct.dwForwardMetric1;
        }

        public RouteTableManager.MIB_IPFORWARDROW GetBaseStruct()
        {
            return new RouteTableManager.MIB_IPFORWARDROW()
            {
                dwForwardDest = RouteTableManager.IpToUint(Dest),
                dwForwardMask = RouteTableManager.IpToUint(Mask),
                dwForwardPolicy = Policy,
                dwForwardNextHop = RouteTableManager.IpToUint(NextHop),
                dwForwardIfIndex = IfIndex,
                dwForwardType = Type,
                dwForwardProto = Proto,
                dwForwardAge = Age,
                dwForwardNextHopAS = NextHopAS,
                dwForwardMetric1 = Metric,
                dwForwardMetric2 = -1,
                dwForwardMetric3 = -1,
                dwForwardMetric4 = -1,
                dwForwardMetric5 = -1
            };
        }
    }
}

 

本文出自 小古Blog,转载时请注明出处及相应链接。

本文永久链接: http://blog.chdz1.com/?post=254

|

发表评论:

电子邮件地址不会被公开。 必填项已用*标注

Ɣ回顶部
sitemap