package discovery import ( "os" "os/exec" "runtime" "strings" ) // lookupMAC 从 ARP 表获取 IP 对应的 MAC 地址(跨平台) // 返回空字符串表示无法获取 func lookupMAC(ip string) string { switch runtime.GOOS { case "linux": return macFromProcNetArp(ip) case "windows": return macFromWindowsArp(ip) default: return macFromUnixArp(ip) } } // macFromProcNetArp 解析 Linux /proc/net/arp func macFromProcNetArp(ip string) string { data, err := os.ReadFile("/proc/net/arp") if err != nil { return "" } for _, line := range strings.Split(string(data), "\n")[1:] { fields := strings.Fields(line) if len(fields) >= 4 && fields[0] == ip { mac := fields[3] if mac != "" && mac != "00:00:00:00:00:00" { return mac } } } return "" } // macFromWindowsArp 解析 Windows `arp -a` 输出 func macFromWindowsArp(ip string) string { out, err := exec.Command("arp", "-a").Output() if err != nil { return "" } for _, line := range strings.Split(string(out), "\n") { fields := strings.Fields(line) if len(fields) >= 2 && fields[0] == ip { mac := strings.ReplaceAll(fields[1], "-", ":") if mac != "" && mac != "00:00:00:00:00:00" { return strings.ToLower(mac) } } } return "" } // macFromUnixArp 解析 macOS/Linux `arp -n` 输出 func macFromUnixArp(ip string) string { out, err := exec.Command("arp", "-n", ip).Output() if err != nil { return "" } for _, line := range strings.Split(string(out), "\n") { fields := strings.Fields(line) for i, f := range fields { if f == "("+ip+")" && i+2 < len(fields) { mac := fields[i+2] if mac != "" && mac != "ff:ff:ff:ff:ff:ff" { return strings.ToLower(mac) } } } } return "" }