Search code examples
goipcidr

Iterating over a multiline variable to return all ips


I'm trying to build a simple port scanner for a beginner golang project and most of the code works as intended, but I'm having a problem with ipv4_gen() function to return all ips that are generated line by line and pass them to another function to scan them currently ipv4_gen() Returns the first line only is there a way I can iterate over the ip variable to returns all the ips line by line?

package main

import (
    "fmt"
    "log"
    "net"
    "strconv"
    "time"
)

func ipv4_gen() string {
    ip, ipnet, err := net.ParseCIDR("192.168.1.1/24")
    if err != nil {
        log.Fatal(err)
    }
    for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
        return ip.String()
    }
    return ip.String()
}

func inc(ip net.IP) {
    for j := len(ip) - 1; j >= 0; j-- {
        ip[j]++
        if ip[j] > 0 {
            break
        }
    }
}

func port_scanner(host string) {
    port := strconv.Itoa(80)
    conn, err := net.DialTimeout("tcp", host+":"+port, 1*time.Second)
    if err == nil {
        fmt.Println("Host:", conn.RemoteAddr().String(), "open")
        conn.Close()
    }
}

func main() {
    port_scanner(ipv4_gen())
}

Here's the link if you wanna run the code https://play.golang.org/p/YWvgnowZzhI


Solution

  • To return multiple results from a function (especially when generating potentially thousands of results) it's idiomatic in Go to use a channel.

    package main
    
    import (
        "fmt"
        "log"
        "net"
        "strconv"
        "time"
    )
    
    func ipv4_gen(out chan string) {
        ip, ipnet, err := net.ParseCIDR("192.168.1.1/24")
        if err != nil {
            log.Fatal(err)
        }
        for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
            out <- ip.String()
        }
        close(out)
    }
    
    func inc(ip net.IP) {
        for j := len(ip) - 1; j >= 0; j-- {
            ip[j]++
            if ip[j] > 0 {
                break
            }
        }
    }
    
    func port_scanner(host string) {
        port := strconv.Itoa(80)
        conn, err := net.DialTimeout("tcp", host+":"+port, 1*time.Second)
        if err == nil {
            fmt.Println("Host:", conn.RemoteAddr().String(), "open")
            conn.Close()
        }
    }
    
    func main() {
        ips := make(chan string)
        go ipv4_gen(ips)
        for s := range ips {
            port_scanner(s)
        }
    }