C# 语言访问 Windows 系统IP路由表的基础类库

68 篇文章 4 订阅
namespace Ppp.Net
{
    using System;
    using System.Collections.Generic;
    using System.Net;
    using global::Ppp.Net.Routing;
    using global::Ppp.Net.Tools;

    public static class Router
    {
        public enum Error
        {
            Success,
            ObjectAlreadyExists,
            NetworkInterfaceNotExists,
            OperationsAreNotSupported,
            PermissionsNotEnough,
            ArgumentOutRangeException,
        }

        private const int ERROR_SUCCESS = 0;
        private const int ERROR_ACCESS_DENIED = 5;
        private const int ERROR_INVALID_PARAMETER = 87;
        private const int ERROR_NOT_FOUND = 1168;
        private const int ERROR_NOT_SUPPORTED = 50;
        private const int ERROR_OBJECT_ALREADY_EXISTS = 5010;

        private static Error ConvertError(int error)
        {
            switch (error)
            {
                case ERROR_SUCCESS:
                    return Error.Success;
                case ERROR_OBJECT_ALREADY_EXISTS:
                    return Error.ObjectAlreadyExists;
                case ERROR_NOT_FOUND:
                    return Error.NetworkInterfaceNotExists;
                case ERROR_NOT_SUPPORTED:
                    return Error.OperationsAreNotSupported;
                case ERROR_ACCESS_DENIED:
                    return Error.PermissionsNotEnough;
                default:
                    return Error.ArgumentOutRangeException;
            };
        }

        public static bool Equals(this IPAddress x, IPAddress y)
        {
            return Route.Equals(x, y);
        }

        public static Route Find(IPAddress destination, IPAddress gateway, out Error error)
        {
            error = Error.ArgumentOutRangeException;
            if (destination == null)
            {
                destination = IPAddress.Any;
            }
            if (gateway == null)
            {
                gateway = IPAddress.Any;
            }
            int errno = RouteTableManager.GetIpForwardEntry(destination, gateway, out Route route);
            error = ConvertError(errno);
            return route;
        }

        public static Route Find(IPAddress destination, out Error error)
        {
            error = Error.ArgumentOutRangeException;
            if (destination == null)
            {
                destination = IPAddress.Any;
            }
            int errno = RouteTableManager.GetIpForwardEntry(destination, out Route route);
            error = ConvertError(errno);
            return route;
        }

        public static Error Set(Route route)
        {
            if (route == null)
            {
                return Error.ArgumentOutRangeException;
            }
            int errno = RouteTableManager.SetIpForwardEntry(route);
            return ConvertError(errno);
        }

        public static Route[] FindAll(out Error error)
        {
            int errno = RouteTableManager.GetIpForwardTable(out Route[] routes);
            error = ConvertError(errno);
            if (routes == null)
            {
                routes = new Route[0];
            }
            return routes;
        }

        public static int Flush(out Error error)
        {
            return Delete(FindAll(out error));
        }

        public static int Create(IEnumerable<Route> routes)
        {
            int events = 0;
            if (routes == null)
            {
                return events;
            }
            foreach (Route route in routes)
            {
                if (route == null)
                {
                    continue;
                }
                int errno = RouteTableManager.CreateIpForwardEntry(route);
                if (errno == ERROR_SUCCESS)
                {
                    events++;
                }
            }
            return events;
        }

        public static int Delete(IEnumerable<Route> routes)
        {
            int events = 0;
            if (routes == null)
            {
                return events;
            }
            foreach (Route route in routes)
            {
                if (route == null)
                {
                    continue;
                }
                int errno = RouteTableManager.DeleteIpForwardEntry(route);
                if (errno == ERROR_SUCCESS)
                {
                    events++;
                }
            }
            return events;
        }

        public static Route[] FindAllAnyAddress(out Error error)
        {
            Route[] routes = FindAll(out error);
            if (routes == null)
            {
                routes = new Route[0];
            }
            if (routes.Length <= 0)
            {
                return routes;
            }
            List<Route> caches = new List<Route>();
            IPAddress cirdMiddleMask = IPAddress.Parse("128.0.0.0"); // 0.0.0.0/1
            foreach (Route route in routes) 
            {
                /* 
                 * +------------------------------------------------------+
                 * + 本子程序仅查找通用规则的以太网卡驱动配置的系统全局路由    +
                 * + 为不保存整个路由表并且清空系统路由表而设计               +
                 * + 仅查找全局路由信息保存并且从内核中移除路由               +
                 * +------------------------------------------------------+
                 *  VNP:PP-TP / L2TP / OpenVNP / SoftEther / SkylakeNAT
                 *  IIF:Realtek / Intel / Ralink / Broadcom / Marvell..... 
                 */
                if (route == null) 
                {
                    continue;
                }
                // 0.0.0.0 MASK 0.0.0.0(以太网卡设备驱动在配置有效的下个跳数[指网关]时为缺省网卡所有IP从此接口出站)
                if (Equals(route.Destination, IPAddress.Any) && Equals(route.Mask, IPAddress.Any))
                {
                    caches.Add(route);
                    continue;
                }
                // 128.0.0.0 MASK 0.0.0.0(多用于点对点虚拟网卡链路-VPN)
                if (Equals(route.Mask, cirdMiddleMask) && Equals(route.Destination, IPAddress.Any))
                {
                    caches.Add(route);
                    continue;
                }
                // 0.0.0.0 MASK 128.0.0.0(多用于点多点虚拟网卡链路-VPN)
                if (Equals(route.Mask, cirdMiddleMask) && Equals(route.Destination, cirdMiddleMask))
                {
                    caches.Add(route);
                    continue;
                }
            }
            return caches.ToArray();
        }

        public static Error DeleteFast(IPAddress destination, IPAddress mask, IPAddress gateway, int metric)
        {
            if (destination == null)
            {
                destination = IPAddress.Any;
            }
            if (mask == null)
            {
                mask = IPAddress.Any;
            }
            if (gateway == null)
            {
                gateway = IPAddress.Any;
            }
            int err = RouteTableManager.GetBestInterface(destination, out uint ifIndex);
            if (err != 0)
            {
                return ConvertError(err);
            }
            err = RouteTableManager.DeleteIpForwardEntry(new Route()
            {
                Destination = destination,
                Mask = mask,
                NextHop = gateway,
                IfIndex = ifIndex,
                Metric = metric,
                Policy = 0,
                Type = RouteTableManager.MIB_IPFORWARD_TYPE.MIB_IPROUTE_TYPE_DIRECT,
                Proto = RouteTableManager.MIB_IPPROTO.MIB_IPPROTO_NETMGMT,
                Age = 0,
                NextHopAS = 0
            });
            return ConvertError(err);
        }

        public static Error Create(IPAddress destination, IPAddress gateway, int metric)
        {
            if (destination == null)
            {
                destination = IPAddress.Any;
            }
            if (gateway == null)
            {
                gateway = IPAddress.Any;
            }
            int error = RouteTableManager.CreateIpForwardEntry(destination, gateway, metric);
            return ConvertError(error);
        }

        public static Error Create(IPAddress destination, IPAddress mask, IPAddress gateway, int metric)
        {
            if (destination == null)
            {
                destination = IPAddress.Any;
            }
            if (mask == null)
            {
                mask = IPAddress.Any;
            }
            if (gateway == null)
            {
                gateway = IPAddress.Any;
            }
            int error = RouteTableManager.CreateIpForwardEntry(destination, mask, gateway, metric);
            return ConvertError(error);
        }

        public static Error Create(IPAddress destination, IPAddress mask, IPAddress gateway, int ifIndex, int metric)
        {
            if (destination == null)
            {
                destination = IPAddress.Any;
            }
            if (mask == null)
            {
                mask = IPAddress.Any;
            }
            if (gateway == null)
            {
                gateway = IPAddress.Any;
            }
            int error = RouteTableManager.CreateIpForwardEntry(destination, mask, gateway, (uint)ifIndex, metric);
            return ConvertError(error);
        }

        public static Error Delete(IPAddress destination)
        {
            if (destination == null)
            {
                destination = IPAddress.Any;
            }
            int error = RouteTableManager.DeleteIpForwardEntry(destination);
            return ConvertError(error);
        }

        public static Error Delete(IPAddress destination, IPAddress gateway)
        {
            if (destination == null)
            {
                destination = IPAddress.Any;
            }
            if (gateway == null)
            {
                gateway = IPAddress.Any;
            }
            int error = RouteTableManager.DeleteIpForwardEntry(destination, gateway);
            return ConvertError(error);
        }

        public static int DeleteFast(IEnumerable<IPAddressRange> addresses, IPAddress gateway)
        {
            return AddDeleteFast(true, addresses, gateway);
        }

        public static int AddFast(IEnumerable<IPAddressRange> addresses, IPAddress gateway)
        {
            return AddDeleteFast(false, addresses, gateway);
        }

        private static int AddDeleteFast(bool deleted, IEnumerable<IPAddressRange> addresses, IPAddress gateway)
        {
            if (gateway == null)
            {
                gateway = IPAddress.Any;
            }
            int events = 0;
            if (addresses == null)
            {
                return events;
            }
            foreach (IPAddressRange i in addresses)
            {
                IPAddress destination = i.Begin;
                IPAddress mask = IPAddress.Any;
                try
                {
                    int crid = i.GetPrefixLength();
                    mask = IPAddressRange.SubnetMaskAddress(crid);
                }
                catch (Exception) { }
                do
                {
                    Router.Error error = Router.Error.OperationsAreNotSupported;
                    if (deleted)
                    {
                        error = Router.DeleteFast(destination, mask, gateway, 1);
                    }
                    else
                    {
                        error = Router.Create(destination, mask, gateway, 1);
                    }
                    if (error == Router.Error.ObjectAlreadyExists || error == Router.Error.Success)
                    {
                        events++;
                    }
                } while (false);
            }
            return events;
        }
    }
}
namespace Ppp.Net.Routing
{
    using System;
    using System.Net;
    using System.Runtime.InteropServices;

    public 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(ref MIB_IPFORWARDROW pRoute);

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

        [DllImport("Iphlpapi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        private static extern int SetIpForwardEntry(ref 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 Route[] ipForwardTable)
        {
            int res = 0;
            int size = Marshal.SizeOf(typeof(MIB_IPFORWARDROW));
            MIB_IPFORWARDTABLE* table = (MIB_IPFORWARDTABLE*)Marshal.AllocHGlobal(size);

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

            if (res == 0)
            {
                ipForwardTable = new Route[(*table).dwNumEntries];
                for (int i = 0; i < ipForwardTable.Length; i++)
                {
                    ipForwardTable[i] = new Route((&(*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 Route bestRoute)
        {
            MIB_IPFORWARDROW pBestRoute;
            var res = GetBestRoute(IpToUint(destAddr), IpToUint(sourceAddr), out pBestRoute);
            bestRoute = new Route(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 Route route)
        {
            route = null;

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

            if (res == 0)
            {
                for (int i = 0; i < ipForwardTable.Length; i++)
                {
                    if (Route.Equals(ipForwardTable[i].Destination, destAddr) && Route.Equals(ipForwardTable[i].NextHop, 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 Route route)
        {
            route = null;

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

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

            return res;
        }

        /// <summary>
        /// 创建路由
        /// </summary>
        /// <param name="route"></param>
        /// <returns></returns>
        public static int CreateIpForwardEntry(Route route)
        {
            if (route == null)
            {
                return ~0;
            }
            MIB_IPFORWARDROW mib = route.GetBaseStruct();
            return CreateIpForwardEntry(ref mib);
        }

        /// <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)
        {
            Route route = new Route()
            {
                Destination = 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(Route route)
        {
            if (route == null)
            {
                return ~0;
            }
            MIB_IPFORWARDROW mib = route.GetBaseStruct();
            return SetIpForwardEntry(ref mib);
        }

        /// <summary>
        /// 删除路由
        /// </summary>
        /// <param name="route"></param>
        /// <returns></returns>
        public static int DeleteIpForwardEntry(Route route)
        {
            if (route == null)
            {
                return ~0;
            }
            MIB_IPFORWARDROW mib = route.GetBaseStruct();
            return DeleteIpForwardEntry(ref mib);
        }

        /// <summary>
        /// 删除路由
        /// </summary>
        /// <param name="destAddr"></param>
        /// <param name="nextHop"></param>
        /// <returns></returns>
        public static int DeleteIpForwardEntry(IPAddress destAddr, IPAddress nextHop)
        {
            Route 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)
        {
            Route 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);
        }
    }
}
namespace Ppp.Net.Routing
{
    using System.Linq;
    using System.Net;
    using System.Net.NetworkInformation;
    using System.Net.Sockets;
    using Ppp.Net.Tun;

    public class Route
    {
        /// <summary>
        /// destination IP address.
        /// </summary>
        public IPAddress Destination { 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 override string ToString()
        {
            return string.Format("ROUTE ADD {0} MASK {1} {2} METRIC {3} IF {4} / {5}",
                this.Destination,
                this.Mask,
                this.NextHop,
                this.Metric,
                this.IfIndex,
                GetNetworkInterfaceAddress(GetNetworkInterface((int)this.IfIndex)));
        }

        public static NetworkInterface GetNetworkInterface(int ifIndex)
        {
            return Layer3Netif.GetNetworkInterface(ifIndex);
        }

        public static IPAddress GetNetworkInterfaceAddress(NetworkInterface ni)
        {
            if (ni == null)
            {
                return IPAddress.Any;
            }
            UnicastIPAddressInformationCollection addressInformationCollection = ni.GetIPProperties().UnicastAddresses;
            UnicastIPAddressInformation addressInformation = addressInformationCollection.FirstOrDefault(i =>
            {
                IPAddress address = i.Address;
                if (address.AddressFamily != AddressFamily.InterNetwork)
                {
                    return false;
                }
                if (Equals(address, IPAddress.Any))
                {
                    return false;
                }
                return true;
            });
            if (addressInformation == null)
            {
                addressInformation = addressInformationCollection.FirstOrDefault(i =>
                {
                    IPAddress address = i.Address;
                    if (address.AddressFamily != AddressFamily.InterNetworkV6)
                    {
                        return false;
                    }
                    if (Equals(address, IPAddress.IPv6Any))
                    {
                        return false;
                    }
                    return true;
                });
            }
            if (addressInformation == null)
            {
                return IPAddress.Any;
            }
            return addressInformation.Address;
        }

        public static bool Equals(IPAddress x, IPAddress y)
        {
            return TapTap2Socket.Equals(x, y);
        }

        public Route()
        {

        }

        public Route(RouteTableManager.MIB_IPFORWARDROW baseStruct)
        {
            Destination = 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(Destination),
                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
            };
        }
    }
}

 

C#基础类库 1.Chart图形 Assistant创建显示图像的标签和文件 OWCChart统计图的封装类 2.Cookie&Session;&Cache;缓存帮助类 CacheHelper C#操作缓存的帮助类,实现了怎么设置缓存,怎么取缓存,怎么清理缓存等方法,只需要调用方法就可以实现 CookieHelper C#操作Cookie的帮助类,添加Cookie,删除Cookie,修改Cookie,清理Cookie SessionHelper C#关于Session的操作,获取Session,设置Session,删除Session使用方便,只需要调用方法就可以了 SessionHelper2 C#关于Session的一些高级操作,比如取Session对象,取Session数据等等 3.CSV文件转换 CsvHelper CSV文件导入DataTable和DataTable导出到Csv文件等操作 4.DEncrypt 加密/解密帮助类 DEncrypt C#DEncrypt加密/DEncrypt解密帮助类 ,多种方式,可以设置Key DESEncrypt C#DESEncrypt加密/DESEncrypt解密帮助类 ,多种方式,可以设置Key Encrypt C#Encrypt--Encrypt加密/Encrypt解密/附加有MD5加密,个人感觉很不错的一个加密类 HashEncode 哈希加密帮助类,得到随机哈希加密字符串,随机哈希数字加密等 MySecurity MySecurity--Security安全加密/Security Base64/Security文件加密,以及一些常用的操作方法 RSACryption RSACryption--RSA加密/RSA解密字符串 RSA加密应用最多是银行接口,这里的方法可以直接使用哦 5.FTP操作类 FTPClient   FTPClient--FTP操作帮助类,FTP上传,FTP下载,FTP文件操作,FTP目录操作 FTPHelper FTPHelper-FTP帮助类,FTP常用操作方法,添加文件,删除文件等 FTPOperater FTP操作帮助类,方法比较多,比较实用 6.JS操作类 JsHelper JsHelper--Javascript操作帮助类,输出各种JS方法,方便不懂JS的人使用,减少代码量 7.JSON 转化类 ConvertJson List转成Json|对象转成Json|集合转成Json|DataSet转成Json|DataTable转成Json|DataReader转成Json等 8.Mime MediaTypes 电子邮件类型帮助类,规定是以Xml,HTML还是文本方式发送邮件 MimeEntity Mime实体帮助类 MimeHeaders mime的Header帮助类 MimeReader mime读取帮助类 QuotedPrintableEncoding mimeEncoding帮助类 9.PDF 转化类 PDFOperation PDFOperation--C#PDF文件操作帮助类 类主要功能有1.构造函数2.私有字段3.设置字体4.设置页面大小 5.实例化文档6.打开文档对象7.关闭打开的文档8.添加段落9.添加图片10.添加链接、点 等功能 10.ResourceManager 操作类 AppMessage app消息格式化类,返加字符串帮助类 ResourceManager C#一个操作Resource的帮助类 ResourceManagerWrapper Resources 操作Resources的帮助类,使用Api的方式 Sample.xml 11.XML操作类 XmlHelper 操作Xml文档的帮助类,主要是添加,删除,修改,查询节点的操作和操作后进行保存的功能。 XMLProcess 操作Xml文档的帮助类,主要是添加,删除,修改,查询节点的操作的功能。 12.弹出消息类 MessageBox JS弹出信息帮助类 ShowMessageBox 相对于MessageBox更丰富的提示类 13.导出Excel 操作类 DataToExcel
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值