package main import ( "bytes" "encoding/hex" "errors" "fmt" "io/fs" "os" "path/filepath" "runtime" "strings" "golang.org/x/sys/windows/registry" ) // ---------- Linux ---------- func duidsLinux() (map[string][]byte, error) { candidates := []string{ "/var/lib/NetworkManager", "/var/lib/dhcp", "/var/lib/systemd/network", "/run/systemd/netif/leases", } out := map[string][]byte{} for _, dir := range candidates { _ = filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { if err != nil || d.IsDir() { return nil } // lease/duid files are small, read entire file buf, err := os.ReadFile(path) if err != nil { return nil } duid := extractDUID(buf) if len(duid) > 0 { out[path] = duid } return nil }) } if len(out) == 0 { return nil, errors.New("keine DUID-Datei gefunden") } return out, nil } // very tolerant parser: tries common patterns func extractDUID(b []byte) []byte { // Pattern „default-duid "\x00\x03\x00\x01\xaa…"“ if bytes.Contains(b, []byte("default-duid")) || bytes.Contains(b, []byte("dhclient.duid")) { start := bytes.IndexByte(b, '"') end := bytes.LastIndexByte(b, '"') if start >= 0 && end > start { hexEsc := b[start+1 : end] hexEsc = bytes.ReplaceAll(hexEsc, []byte(`\x`), nil) duid, _ := hex.DecodeString(string(hexEsc)) return duid } } // systemd-networkd file: plain hex without 0x if allHex(b) { duid, _ := hex.DecodeString(strings.TrimSpace(string(b))) return duid } return nil } func allHex(b []byte) bool { for _, c := range bytes.TrimSpace(b) { if !strings.ContainsRune("0123456789abcdefABCDEF", rune(c)) { return false } } return true } // ---------- Windows ---------- func duidsWindows() (map[string][]byte, error) { k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters`, registry.READ) if err != nil { return nil, err } defer k.Close() val, _, err := k.GetBinaryValue("Dhcpv6DUID") if err != nil { return nil, err } return map[string][]byte{"registry": val}, nil } // ---------- macOS (scutil) ---------- // (Beispielskizze – nicht implementiert) // func duidsDarwin() ... // ---------- main ---------- func main() { var duids map[string][]byte var err error switch runtime.GOOS { case "windows": duids, err = duidsWindows() default: // linux, darwin, ... duids, err = duidsLinux() } if err != nil { fmt.Fprintln(os.Stderr, "Fehler:", err) os.Exit(1) } hostName, _ := os.Hostname() for _, d := range duids { fmt.Printf("%s", hex.EncodeToString(d)) fmt.Printf("%s", hostName) } }