package dhcp import ( "bufio" "os" "os/exec" "regexp" "strings" "github.com/nemunaire/repeater/internal/models" ) // parseDHCPLeases reads and parses DHCP lease file func parseDHCPLeases(path string) ([]models.DHCPLease, error) { var leases []models.DHCPLease file, err := os.Open(path) if err != nil { return leases, err } defer file.Close() scanner := bufio.NewScanner(file) var currentLease models.DHCPLease for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) fields := strings.Fields(line) switch { case strings.HasPrefix(line, "lease "): if len(fields) < 2 { continue } currentLease = models.DHCPLease{IP: fields[1]} case strings.Contains(line, "hardware ethernet"): if len(fields) < 3 { continue } currentLease.MAC = strings.TrimSuffix(fields[2], ";") case strings.Contains(line, "client-hostname"): if len(fields) < 2 { continue } currentLease.Hostname = strings.Trim(fields[1], `";`) case line == "}": if currentLease.IP != "" && currentLease.MAC != "" { leases = append(leases, currentLease) } currentLease = models.DHCPLease{} } } return leases, nil } // getARPInfo retrieves ARP table information using arp command // Returns a map of IP -> MAC address func getARPInfo() (map[string]string, error) { arpInfo := make(map[string]string) cmd := exec.Command("arp", "-a") output, err := cmd.Output() if err != nil { return arpInfo, err } lines := strings.Split(string(output), "\n") for _, line := range lines { if matches := regexp.MustCompile(`\(([^)]+)\) at ([0-9a-fA-F:]{17})`).FindStringSubmatch(line); len(matches) > 2 { ip := matches[1] mac := matches[2] arpInfo[ip] = mac } } return arpInfo, nil }