(reader io.Reader)
| 30 | } |
| 31 | |
| 32 | func Iterate(reader io.Reader) <-chan Host { |
| 33 | scanner := bufio.NewScanner(reader) |
| 34 | hostChan := make(chan Host) |
| 35 | go func() { |
| 36 | defer close(hostChan) |
| 37 | for scanner.Scan() { |
| 38 | line := strings.TrimSpace(scanner.Text()) |
| 39 | if line == "" { |
| 40 | continue |
| 41 | } |
| 42 | ip := net.ParseIP(line) |
| 43 | if ip != nil && (ip.To4() != nil || enableIPv6) { |
| 44 | // ip address |
| 45 | hostChan <- Host{ |
| 46 | IP: ip, |
| 47 | Origin: line, |
| 48 | Type: HostTypeIP, |
| 49 | } |
| 50 | continue |
| 51 | } |
| 52 | _, _, err := net.ParseCIDR(line) |
| 53 | if err == nil { |
| 54 | // ip cidr |
| 55 | p, err := netip.ParsePrefix(line) |
| 56 | if err != nil { |
| 57 | slog.Warn("Invalid cidr", "cidr", line, "err", err) |
| 58 | } |
| 59 | if !p.Addr().Is4() && !enableIPv6 { |
| 60 | continue |
| 61 | } |
| 62 | p = p.Masked() |
| 63 | addr := p.Addr() |
| 64 | for { |
| 65 | if !p.Contains(addr) { |
| 66 | break |
| 67 | } |
| 68 | ip = net.ParseIP(addr.String()) |
| 69 | if ip != nil { |
| 70 | hostChan <- Host{ |
| 71 | IP: ip, |
| 72 | Origin: line, |
| 73 | Type: HostTypeCIDR, |
| 74 | } |
| 75 | } |
| 76 | addr = addr.Next() |
| 77 | } |
| 78 | continue |
| 79 | } |
| 80 | if ValidateDomainName(line) { |
| 81 | // domain |
| 82 | hostChan <- Host{ |
| 83 | IP: nil, |
| 84 | Origin: line, |
| 85 | Type: HostTypeDomain, |
| 86 | } |
| 87 | continue |
| 88 | } |
| 89 | slog.Warn("Not a valid IP, IP CIDR or domain", "line", line) |
no test coverage detected