using System.Diagnostics; using System.Runtime.InteropServices; using System.Text.RegularExpressions; /// /// ARP 记录管理静态类(跨平台支持) /// public static class Arp { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 读取所有 ARP 记录 /// /// ARP 记录列表 public static async Task> GetArpTableAsync() { var entries = new List(); try { string command = GetArpListCommand(); var result = await ExecuteCommandAsync(command); if (result.IsSuccess) { var lines = result.Output.Split('\n', StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var entry = ParseArpEntry(line); if (entry != null) { entries.Add(entry); } } } } catch (Exception ex) { throw new Exception($"读取 ARP 表失败: {ex.Message}"); } return entries; } /// /// 通过 Ping 动态更新指定 IP 的 ARP 记录 /// /// 要更新的 IP 地址 /// 是否成功发送 Ping public static async Task 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; } } /// /// 添加 ARP 记录 /// /// IP 地址 /// MAC 地址 /// 网络接口名称(可选) /// 是否成功 public static async Task AddArpEntryAsync(string ipAddress, string macAddress, string? interfaceName = null) { if (string.IsNullOrWhiteSpace(ipAddress)) throw new ArgumentException("IP 地址不能为空", nameof(ipAddress)); if (string.IsNullOrWhiteSpace(macAddress)) throw new ArgumentException("MAC 地址不能为空", nameof(macAddress)); try { // 格式化 MAC 地址以适配不同操作系统 string formattedMac = FormatMacAddress(macAddress); string command = GetArpAddCommand(ipAddress, formattedMac, interfaceName); var result = await ExecuteCommandAsync(command); return result.IsSuccess; } catch (Exception ex) { throw new Exception($"添加 ARP 记录失败: {ex.Message}"); } } /// /// 删除 ARP 记录 /// /// 要删除的 IP 地址 /// 网络接口名称(可选) /// 是否成功 public static async Task DeleteArpEntryAsync(string ipAddress, string? interfaceName = null) { if (string.IsNullOrWhiteSpace(ipAddress)) throw new ArgumentException("IP 地址不能为空", nameof(ipAddress)); try { string command = GetArpDeleteCommand(ipAddress, interfaceName); var result = await ExecuteCommandAsync(command); return result.IsSuccess; } catch (Exception ex) { throw new Exception($"删除 ARP 记录失败: {ex.Message}"); } } /// /// 清空所有 ARP 记录 /// /// 是否成功 public static async Task ClearArpTableAsync() { try { string command = GetArpClearCommand(); var result = await ExecuteCommandAsync(command); return result.IsSuccess; } catch (Exception ex) { throw new Exception($"清空 ARP 表失败: {ex.Message}"); } } /// /// 查询特定 IP 的 ARP 记录 /// /// IP 地址 /// ARP 记录,如果不存在则返回 null public static async Task GetArpEntryAsync(string ipAddress) { if (string.IsNullOrWhiteSpace(ipAddress)) throw new ArgumentException("IP 地址不能为空", nameof(ipAddress)); try { string command = GetArpQueryCommand(ipAddress); var result = await ExecuteCommandAsync(command); if (result.IsSuccess) { var lines = result.Output.Split('\n', StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var entry = ParseArpEntry(line); if (entry != null && entry.IpAddress == ipAddress) { return entry; } } } } catch (Exception ex) { throw new Exception($"查询 ARP 记录失败: {ex.Message}"); } return null; } /// /// 获取 ARP 列表命令 /// private static string GetArpListCommand() { return "arp -a"; } /// /// 获取 ARP 添加命令 /// private static string GetArpAddCommand(string ipAddress, string macAddress, string? interfaceName) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return string.IsNullOrWhiteSpace(interfaceName) ? $"arp -s {ipAddress} {macAddress}" : $"arp -s {ipAddress} {macAddress} {interfaceName}"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return string.IsNullOrWhiteSpace(interfaceName) ? $"arp -s {ipAddress} {macAddress}" : $"arp -s {ipAddress} {macAddress} -i {interfaceName}"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return string.IsNullOrWhiteSpace(interfaceName) ? $"arp -s {ipAddress} {macAddress}" : $"arp -s {ipAddress} {macAddress} ifscope {interfaceName}"; } else { throw new PlatformNotSupportedException("不支持的操作系统平台"); } } /// /// 获取 ARP 删除命令 /// private static string GetArpDeleteCommand(string ipAddress, string? interfaceName) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return $"arp -d {ipAddress}"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return string.IsNullOrWhiteSpace(interfaceName) ? $"arp -d {ipAddress}" : $"arp -d {ipAddress} -i {interfaceName}"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return string.IsNullOrWhiteSpace(interfaceName) ? $"arp -d {ipAddress}" : $"arp -d {ipAddress} ifscope {interfaceName}"; } else { throw new PlatformNotSupportedException("不支持的操作系统平台"); } } /// /// 获取 ARP 清空命令 /// private static string GetArpClearCommand() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return "arp -d *"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return "ip neigh flush all"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return "arp -d -a"; } else { throw new PlatformNotSupportedException("不支持的操作系统平台"); } } /// /// 获取 ARP 查询命令 /// private static string GetArpQueryCommand(string ipAddress) { return $"arp -a {ipAddress}"; } /// /// 执行系统命令 /// /// 命令 /// 命令执行结果 private static async Task ExecuteCommandAsync(string command) { try { ProcessStartInfo processInfo; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { processInfo = new ProcessStartInfo { FileName = "cmd.exe", Arguments = $"/c {command}", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; } else { processInfo = new ProcessStartInfo { FileName = "/bin/bash", Arguments = $"-c \"{command}\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; } logger.Debug($"Executing command: {processInfo.FileName} {processInfo.Arguments}"); using var process = new Process { StartInfo = processInfo }; process.Start(); var output = await process.StandardOutput.ReadToEndAsync(); var error = await process.StandardError.ReadToEndAsync(); 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, Output = output, Error = error, ExitCode = process.ExitCode }; } catch (Exception ex) { logger.Error(ex, $"Command execution failed: {command}"); return new CommandResult { IsSuccess = false, Error = ex.Message, ExitCode = -1 }; } } /// /// 解析 ARP 记录行 /// /// ARP 记录行 /// 解析后的 ARP 记录 private static ArpEntry? ParseArpEntry(string line) { if (string.IsNullOrWhiteSpace(line)) return null; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return ParseWindowsArpEntry(line); } else { return ParseUnixArpEntry(line); } } /// /// 解析 Windows ARP 记录 /// private static ArpEntry? ParseWindowsArpEntry(string line) { // 跳过空行和标题行 if (string.IsNullOrWhiteSpace(line) || line.Contains("Interface:") || line.Contains("Internet Address") || line.Contains("Physical Address") || line.Contains("Type")) { return null; } // Windows arp -a 输出格式: IP地址 物理地址 类型 // 示例: 172.6.0.1 e4-3a-6e-29-c3-5b dynamic var pattern = @"^\s*(\d+\.\d+\.\d+\.\d+)\s+([a-fA-F0-9-]{17})\s+(\w+)\s*$"; var match = Regex.Match(line, pattern); if (match.Success) { return new ArpEntry { IpAddress = match.Groups[1].Value, MacAddress = FormatMacAddress(match.Groups[2].Value), // 格式化 MAC 地址 Type = match.Groups[3].Value }; } return null; } /// /// 解析 Unix/Linux ARP 记录 /// private static ArpEntry? ParseUnixArpEntry(string line) { // 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) { return new ArpEntry { Hostname = match.Groups[1].Value, IpAddress = match.Groups[2].Value, MacAddress = FormatMacAddress(match.Groups[3].Value), // 格式化 MAC 地址 Type = match.Groups[5].Value, Interface = match.Groups[6].Value }; } // 匹配简单格式: ip mac interface var simplePattern = @"(\d+\.\d+\.\d+\.\d+)\s+([a-fA-F0-9:]{17})\s+(\S+)"; var simpleMatch = Regex.Match(line, simplePattern); if (simpleMatch.Success) { return new ArpEntry { IpAddress = simpleMatch.Groups[1].Value, MacAddress = FormatMacAddress(simpleMatch.Groups[2].Value), // 格式化 MAC 地址 Interface = simpleMatch.Groups[3].Value }; } return null; } /// /// 判断当前进程是否具有管理员(或 root)权限 /// /// 如果有管理员权限返回 true,否则返回 false 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"); } } /// /// 检查指定 IP 是否存在对应的 MAC,如果不存在则删除原有 ARP 记录并新增 /// /// IP 地址 /// MAC 地址 /// 网络接口名称(可选) /// 是否成功 public static async Task CheckOrAddAsync(string ipAddress, string macAddress, string? interfaceName = null) { if (string.IsNullOrWhiteSpace(ipAddress)) throw new ArgumentException("IP 地址不能为空", nameof(ipAddress)); if (string.IsNullOrWhiteSpace(macAddress)) throw new ArgumentException("MAC 地址不能为空", nameof(macAddress)); // 格式化 MAC 地址以适配不同操作系统 string formattedMac = FormatMacAddress(macAddress); var entry = await GetArpEntryAsync(ipAddress); if (entry != null && string.Equals(FormatMacAddress(entry.MacAddress), formattedMac, StringComparison.OrdinalIgnoreCase)) { // 已存在且 MAC 匹配,无需操作 return true; } // 若存在但 MAC 不匹配,先删除 if (entry != null) { await DeleteArpEntryAsync(ipAddress, interfaceName); } // 新增 ARP 记录 return await AddArpEntryAsync(ipAddress, formattedMac, interfaceName); } /// /// 格式化 MAC 地址为指定平台格式 /// /// 原始 MAC 地址 /// 格式化后的 MAC 地址 public static string FormatMacAddress(string macAddress) { if (string.IsNullOrWhiteSpace(macAddress)) return string.Empty; var cleaned = macAddress.Replace("-", "").Replace(":", "").ToLowerInvariant(); if (cleaned.Length != 12) return macAddress; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // Windows: XX-XX-XX-XX-XX-XX return string.Join("-", Enumerable.Range(0, 6).Select(i => cleaned.Substring(i * 2, 2))); } else { // Unix/Linux/macOS: xx:xx:xx:xx:xx:xx return string.Join(":", Enumerable.Range(0, 6).Select(i => cleaned.Substring(i * 2, 2))); } } } /// /// ARP 记录条目 /// public class ArpEntry { /// /// [TODO:description] /// public string Hostname { get; set; } = string.Empty; /// /// [TODO:description] /// public string IpAddress { get; set; } = string.Empty; /// /// [TODO:description] /// public string MacAddress { get; set; } = string.Empty; /// /// [TODO:description] /// public string Type { get; set; } = string.Empty; /// /// [TODO:description] /// public string Interface { get; set; } = string.Empty; /// /// [TODO:description] /// public override string ToString() { return $"{IpAddress} -> {MacAddress} ({Interface})"; } } /// /// 命令执行结果 /// public class CommandResult { /// /// [TODO:description] /// public bool IsSuccess { get; set; } /// /// [TODO:description] /// public string Output { get; set; } = string.Empty; /// /// [TODO:description] /// public string Error { get; set; } = string.Empty; /// /// [TODO:description] /// public int ExitCode { get; set; } }