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