You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
7.3 KiB
168 lines
7.3 KiB
7 days ago
|
using System.Numerics;
|
||
|
using CoreAgent.Domain.Interfaces;
|
||
|
|
||
|
namespace CoreAgent.Infrastructure.Network;
|
||
|
|
||
|
/// <summary>
|
||
|
/// 提供IP地址相关的工具方法
|
||
|
/// </summary>
|
||
|
public static class IPAddressUtils
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// 检查两个IPv4地址是否在同一个子网内
|
||
|
/// </summary>
|
||
|
/// <param name="ip1">第一个IP地址</param>
|
||
|
/// <param name="ip2">第二个IP地址</param>
|
||
|
/// <param name="subnetMask">子网掩码</param>
|
||
|
/// <returns>如果两个IP地址在同一个子网内返回true,否则返回false</returns>
|
||
|
/// <exception cref="ArgumentException">当IP地址或子网掩码不是IPv4格式时抛出</exception>
|
||
|
public static bool IsSameIPv4Subnet(System.Net.IPAddress ip1, System.Net.IPAddress ip2, System.Net.IPAddress subnetMask)
|
||
|
{
|
||
|
if (ip1.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork ||
|
||
|
ip2.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork ||
|
||
|
subnetMask.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)
|
||
|
{
|
||
|
throw new ArgumentException("IP addresses and subnet mask must be IPv4.");
|
||
|
}
|
||
|
|
||
|
byte[] ip1Bytes = ip1.GetAddressBytes();
|
||
|
byte[] ip2Bytes = ip2.GetAddressBytes();
|
||
|
byte[] subnetBytes = subnetMask.GetAddressBytes();
|
||
|
|
||
|
byte[] network1 = new byte[4];
|
||
|
byte[] network2 = new byte[4];
|
||
|
|
||
|
for (int i = 0; i < 4; i++)
|
||
|
{
|
||
|
network1[i] = (byte)(ip1Bytes[i] & subnetBytes[i]);
|
||
|
network2[i] = (byte)(ip2Bytes[i] & subnetBytes[i]);
|
||
|
}
|
||
|
|
||
|
return new System.Net.IPAddress(network1).Equals(new System.Net.IPAddress(network2));
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 检查两个IPv6地址是否在同一个子网内
|
||
|
/// </summary>
|
||
|
/// <param name="ip1">第一个IP地址</param>
|
||
|
/// <param name="ip2">第二个IP地址</param>
|
||
|
/// <param name="prefixLength">前缀长度</param>
|
||
|
/// <returns>如果两个IP地址在同一个子网内返回true,否则返回false</returns>
|
||
|
/// <exception cref="ArgumentException">当IP地址不是IPv6格式时抛出</exception>
|
||
|
public static bool IsSameIPv6Subnet(System.Net.IPAddress ip1, System.Net.IPAddress ip2, int prefixLength)
|
||
|
{
|
||
|
if (ip1.AddressFamily != System.Net.Sockets.AddressFamily.InterNetworkV6 ||
|
||
|
ip2.AddressFamily != System.Net.Sockets.AddressFamily.InterNetworkV6)
|
||
|
{
|
||
|
throw new ArgumentException("IP addresses must be IPv6.");
|
||
|
}
|
||
|
|
||
|
BigInteger ip1Value = new BigInteger(ip1.GetAddressBytes());
|
||
|
BigInteger ip2Value = new BigInteger(ip2.GetAddressBytes());
|
||
|
|
||
|
BigInteger mask = BigInteger.One << (128 - prefixLength);
|
||
|
mask -= BigInteger.One;
|
||
|
mask = ~mask;
|
||
|
|
||
|
return (ip1Value & mask) == (ip2Value & mask);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 获取系统的IPv4地址列表
|
||
|
/// </summary>
|
||
|
/// <param name="commandStrategyFactory">命令策略工厂</param>
|
||
|
/// <param name="source">取消令牌源</param>
|
||
|
/// <param name="logger">日志记录器</param>
|
||
|
/// <returns>IPv4地址列表</returns>
|
||
|
public static async Task<IEnumerable<string>> CheckAddressIPv4(ICommandStrategyFactory commandStrategyFactory, CancellationTokenSource source)
|
||
|
{
|
||
|
List<string> addrs = new List<string>();
|
||
|
var inet4result = await commandStrategyFactory.CreateStrategy().ExecuteBufferedAsync("ifconfig | grep 'inet ' | awk '{print $2}'", source);
|
||
|
if (!string.IsNullOrWhiteSpace(inet4result))
|
||
|
addrs.AddRange(RemoveNewLines(inet4result));
|
||
|
return addrs;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 获取系统的IPv6地址列表
|
||
|
/// </summary>
|
||
|
/// <param name="commandStrategyFactory">命令策略工厂</param>
|
||
|
/// <param name="source">取消令牌源</param>
|
||
|
/// <param name="logger">日志记录器</param>
|
||
|
/// <returns>IPv6地址列表</returns>
|
||
|
public static async Task<IEnumerable<string>> CheckAddressIPv6(ICommandStrategyFactory commandStrategyFactory, CancellationTokenSource source)
|
||
|
{
|
||
|
List<string> addrs = new List<string>();
|
||
|
var inet6result = await commandStrategyFactory.CreateStrategy().ExecuteBufferedAsync("ifconfig | grep 'inet6 ' | awk '{print $2}'", source);
|
||
|
if (!string.IsNullOrWhiteSpace(inet6result))
|
||
|
addrs.AddRange(RemoveNewLines(inet6result));
|
||
|
return addrs;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 获取系统的IPv4地址和子网掩码列表
|
||
|
/// </summary>
|
||
|
/// <param name="commandStrategyFactory">命令策略工厂</param>
|
||
|
/// <param name="source">取消令牌源</param>
|
||
|
/// <param name="logger">日志记录器</param>
|
||
|
/// <returns>IPv4地址和子网掩码的元组列表</returns>
|
||
|
public static async Task<List<(string ipv4, string mask)>> CheckAddressIPv4Mask(ICommandStrategyFactory commandStrategyFactory, CancellationTokenSource source)
|
||
|
{
|
||
|
List<(string ipv4, string mask)> addrs = new List<(string ipv4, string mask)>();
|
||
|
var inet4result = await commandStrategyFactory.CreateStrategy().ExecuteBufferedAsync("ifconfig | grep 'inet ' | awk '{print $2\\\"|\\\"$4}'", source);
|
||
|
if (!string.IsNullOrWhiteSpace(inet4result))
|
||
|
addrs.AddRange(RemoveNewLines(inet4result).Select(s => (s.Split("|")[0], s.Split("|")[1])));
|
||
|
return addrs;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 获取系统的IPv6地址和前缀长度列表
|
||
|
/// </summary>
|
||
|
/// <param name="commandStrategyFactory">命令策略工厂</param>
|
||
|
/// <param name="source">取消令牌源</param>
|
||
|
/// <param name="logger">日志记录器</param>
|
||
|
/// <returns>IPv6地址和前缀长度的元组列表</returns>
|
||
|
public static async Task<List<(string ipv6, string Prefix)>> CheckAddressIPv6Prefix(ICommandStrategyFactory commandStrategyFactory, CancellationTokenSource source)
|
||
|
{
|
||
|
List<(string ipv6, string Prefix)> addrs = new List<(string ipv6, string Prefix)>();
|
||
|
var inet6result = await commandStrategyFactory.CreateStrategy().ExecuteBufferedAsync("ifconfig | grep 'inet6 ' | awk '{print $2\\\"|\\\"$4}'", source);
|
||
|
if (!string.IsNullOrWhiteSpace(inet6result))
|
||
|
addrs.AddRange(RemoveNewLines(inet6result).Select(s => (s.Split("|")[0], s.Split("|")[1])));
|
||
|
return addrs;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 计算两个IP地址的匹配位数
|
||
|
/// </summary>
|
||
|
/// <param name="ip1">第一个IP地址</param>
|
||
|
/// <param name="ip2">第二个IP地址</param>
|
||
|
/// <returns>匹配的位数</returns>
|
||
|
public static int GetMatchingBits(string ip1, string ip2)
|
||
|
{
|
||
|
byte[] bytes1 = System.Net.IPAddress.Parse(ip1).GetAddressBytes();
|
||
|
byte[] bytes2 = System.Net.IPAddress.Parse(ip2).GetAddressBytes();
|
||
|
int matchingBits = 0;
|
||
|
for (int i = 0; i < bytes1.Length; i++)
|
||
|
{
|
||
|
int diff = bytes1[i] ^ bytes2[i]; // 异或计算不同位
|
||
|
for (int bit = 7; bit >= 0; bit--)
|
||
|
{
|
||
|
if ((diff & (1 << bit)) == 0)
|
||
|
matchingBits++;
|
||
|
else
|
||
|
return matchingBits;
|
||
|
}
|
||
|
}
|
||
|
return matchingBits;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 移除字符串中的换行符并分割成数组
|
||
|
/// </summary>
|
||
|
/// <param name="input">输入字符串</param>
|
||
|
/// <returns>分割后的字符串数组</returns>
|
||
|
private static string[] RemoveNewLines(string input)
|
||
|
{
|
||
|
return input.Split("\n", StringSplitOptions.RemoveEmptyEntries);
|
||
|
}
|
||
|
}
|