feat: 添加arp支持,仅支持管理员模式
This commit is contained in:
@@ -7,6 +7,8 @@ using System.Text.RegularExpressions;
|
||||
/// </summary>
|
||||
public static class Arp
|
||||
{
|
||||
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
/// <summary>
|
||||
/// 读取所有 ARP 记录
|
||||
/// </summary>
|
||||
@@ -41,6 +43,28 @@ public static class Arp
|
||||
return entries;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通过 Ping 动态更新指定 IP 的 ARP 记录
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">要更新的 IP 地址</param>
|
||||
/// <returns>是否成功发送 Ping</returns>
|
||||
public static async Task<bool> UpdateArpEntryByPingAsync(string ipAddress)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ipAddress))
|
||||
throw new ArgumentException("IP 地址不能为空", nameof(ipAddress));
|
||||
|
||||
try
|
||||
{
|
||||
using var ping = new System.Net.NetworkInformation.Ping();
|
||||
var reply = await ping.SendPingAsync(ipAddress, 100);
|
||||
return reply.Status == System.Net.NetworkInformation.IPStatus.Success;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加 ARP 记录
|
||||
/// </summary>
|
||||
@@ -48,7 +72,7 @@ public static class Arp
|
||||
/// <param name="macAddress">MAC 地址</param>
|
||||
/// <param name="interfaceName">网络接口名称(可选)</param>
|
||||
/// <returns>是否成功</returns>
|
||||
public static async Task<bool> AddArpEntryAsync(string ipAddress, string macAddress, string interfaceName = null)
|
||||
public static async Task<bool> AddArpEntryAsync(string ipAddress, string macAddress, string? interfaceName = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ipAddress))
|
||||
throw new ArgumentException("IP 地址不能为空", nameof(ipAddress));
|
||||
@@ -74,7 +98,7 @@ public static class Arp
|
||||
/// <param name="ipAddress">要删除的 IP 地址</param>
|
||||
/// <param name="interfaceName">网络接口名称(可选)</param>
|
||||
/// <returns>是否成功</returns>
|
||||
public static async Task<bool> DeleteArpEntryAsync(string ipAddress, string interfaceName = null)
|
||||
public static async Task<bool> DeleteArpEntryAsync(string ipAddress, string? interfaceName = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ipAddress))
|
||||
throw new ArgumentException("IP 地址不能为空", nameof(ipAddress));
|
||||
@@ -149,15 +173,13 @@ public static class Arp
|
||||
/// </summary>
|
||||
private static string GetArpListCommand()
|
||||
{
|
||||
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||
? "arp -a"
|
||||
: "arp -a";
|
||||
return "arp -a";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 ARP 添加命令
|
||||
/// </summary>
|
||||
private static string GetArpAddCommand(string ipAddress, string macAddress, string interfaceName)
|
||||
private static string GetArpAddCommand(string ipAddress, string macAddress, string? interfaceName)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
@@ -186,7 +208,7 @@ public static class Arp
|
||||
/// <summary>
|
||||
/// 获取 ARP 删除命令
|
||||
/// </summary>
|
||||
private static string GetArpDeleteCommand(string ipAddress, string interfaceName)
|
||||
private static string GetArpDeleteCommand(string ipAddress, string? interfaceName)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
@@ -238,14 +260,7 @@ public static class Arp
|
||||
/// </summary>
|
||||
private static string GetArpQueryCommand(string ipAddress)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return $"arp -a {ipAddress}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"arp -n {ipAddress}";
|
||||
}
|
||||
return $"arp -a {ipAddress}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -284,6 +299,8 @@ public static class Arp
|
||||
};
|
||||
}
|
||||
|
||||
logger.Debug($"Executing command: {processInfo.FileName} {processInfo.Arguments}");
|
||||
|
||||
using var process = new Process { StartInfo = processInfo };
|
||||
process.Start();
|
||||
|
||||
@@ -292,6 +309,11 @@ public static class Arp
|
||||
|
||||
await process.WaitForExitAsync();
|
||||
|
||||
logger.Debug($"Command output: {output}");
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
logger.Debug($"Command error: {error}");
|
||||
logger.Debug($"Command exit code: {process.ExitCode}");
|
||||
|
||||
return new CommandResult
|
||||
{
|
||||
IsSuccess = process.ExitCode == 0,
|
||||
@@ -302,6 +324,7 @@ public static class Arp
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, $"Command execution failed: {command}");
|
||||
return new CommandResult
|
||||
{
|
||||
IsSuccess = false,
|
||||
@@ -358,8 +381,8 @@ public static class Arp
|
||||
/// </summary>
|
||||
private static ArpEntry? ParseUnixArpEntry(string line)
|
||||
{
|
||||
// Unix/Linux arp -a 输出格式: hostname (ip) at mac [ether] on interface
|
||||
var pattern = @"(\S+)\s+\((\d+\.\d+\.\d+\.\d+)\)\s+at\s+([a-fA-F0-9:]{17})\s+\[(\w+)\]\s+on\s+(\S+)";
|
||||
// Unix/Linux arp -a 输出格式: hostname (ip) at mac [ether] PERM on interface
|
||||
var pattern = @"(\S+)\s+\((\d+\.\d+\.\d+\.\d+)\)\s+at\s+([a-fA-F0-9:]{17})\s+\[(\w+)\]\s+(\w+)\s+on\s+(\S+)";
|
||||
var match = Regex.Match(line, pattern);
|
||||
|
||||
if (match.Success)
|
||||
@@ -369,8 +392,8 @@ public static class Arp
|
||||
Hostname = match.Groups[1].Value,
|
||||
IpAddress = match.Groups[2].Value,
|
||||
MacAddress = match.Groups[3].Value,
|
||||
Type = match.Groups[4].Value,
|
||||
Interface = match.Groups[5].Value
|
||||
Type = match.Groups[5].Value,
|
||||
Interface = match.Groups[6].Value
|
||||
};
|
||||
}
|
||||
|
||||
@@ -390,6 +413,26 @@ public static class Arp
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断当前进程是否具有管理员(或 root)权限
|
||||
/// </summary>
|
||||
/// <returns>如果有管理员权限返回 true,否则返回 false</returns>
|
||||
public static bool IsAdministrator()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
// Windows: 检查当前用户是否为管理员
|
||||
using var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
|
||||
var principal = new System.Security.Principal.WindowsPrincipal(identity);
|
||||
return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unix/Linux/macOS: 检查是否为 root 用户
|
||||
return Environment.UserName == "root" || (Environment.GetEnvironmentVariable("USER") == "root");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -397,12 +440,30 @@ public static class Arp
|
||||
/// </summary>
|
||||
public class ArpEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public string Hostname { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public string IpAddress { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public string MacAddress { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public string Type { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public string Interface { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{IpAddress} -> {MacAddress} ({Interface})";
|
||||
@@ -414,8 +475,20 @@ public class ArpEntry
|
||||
/// </summary>
|
||||
public class CommandResult
|
||||
{
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public bool IsSuccess { get; set; }
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public string Output { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public string Error { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
public int ExitCode { get; set; }
|
||||
}
|
||||
|
@@ -3,6 +3,8 @@
|
||||
/// </summary>
|
||||
public static class MsgBus
|
||||
{
|
||||
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
private static readonly UDPServer udpServer = new UDPServer(1234, 12);
|
||||
/// <summary>
|
||||
/// 获取UDP服务器
|
||||
@@ -19,8 +21,13 @@ public static class MsgBus
|
||||
/// 通信总线初始化
|
||||
/// </summary>
|
||||
/// <returns>无</returns>
|
||||
public static void Init()
|
||||
public async static void Init()
|
||||
{
|
||||
if (!Arp.IsAdministrator())
|
||||
{
|
||||
logger.Error($"非管理员运行,ARP无法更新,请用管理员权限运行");
|
||||
// throw new Exception($"非管理员运行,ARP无法更新,请用管理员权限运行");
|
||||
}
|
||||
udpServer.Start();
|
||||
isRunning = true;
|
||||
}
|
||||
|
@@ -128,7 +128,7 @@ public class UDPServer
|
||||
if (IsPortInUse(currentPort))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
$"Port {currentPort} is already in use.",
|
||||
$"端口{currentPort}已被占用,无法启动UDP Server",
|
||||
nameof(port)
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user