From 07811791067d69cfc59fd65f8ea27af86a022e7d Mon Sep 17 00:00:00 2001 From: Shivam Patel Date: Sun, 3 Feb 2019 12:19:35 -0800 Subject: [PATCH] First Commit --- .gitignore | 1 + Makefile | 7 ++++ README.md | 45 +++++++++++++++++++++ cidr2ip.go | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++ cidrs.txt | 6 +++ 5 files changed, 173 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 cidr2ip.go create mode 100644 cidrs.txt diff --git a/.gitignore b/.gitignore index f1c181e..220181b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.dll *.so *.dylib +binaries/* # Test binary, build with `go test -c` *.test diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..da8b3a3 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +all: + GOOS=windows GOARCH=386 go build -o binaries/cidr2ip-win32.exe cidr2ip.go + GOOS=windows GOARCH=amd64 go build -o binaries/cidr2ip-win64.exe cidr2ip.go + GOOS=linux GOARCH=386 go build -o binaries/cidr2ip-linux32 cidr2ip.go + GOOS=linux GOARCH=amd64 go build -o binaries/cidr2ip-linux64 cidr2ip.go + GOOS=darwin GOARCH=386 go build -o binaries/cidr2ip-osx32 cidr2ip.go + GOOS=darwin GOARCH=amd64 go build -o binaries/cidr2ip-osx64 cidr2ip.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..346c867 --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +#cidr2ip + +This program converts IPv4 CIDR blocks into their constituent IP addresses. + +### Input modes + +1. Commnd line arguments +``` +code@express:~$ cidr2ip 10.0.0.0/30 192.68.0.0/30 +10.0.0.1 +10.0.0.2 +192.68.0.1 +192.68.0.2 +``` + +2. Piped input +``` +code@express:~$ cat cidrs.txt | cidr2ip +192.168.0.101 +192.168.0.102 +``` + +3. File input +``` +code@express:~$ cidr2ip -f cidrs.txt +192.168.0.101 +192.168.0.102 +``` + +### Install + +#### Download from the releases pages + +Download pre-built binary from the release page. +``` + +``` + +#### Use `go get` + +If you have `golang` tools installed, you can download and build the source code +locally as follows: +``` + +``` diff --git a/cidr2ip.go b/cidr2ip.go new file mode 100644 index 0000000..06a2f1e --- /dev/null +++ b/cidr2ip.go @@ -0,0 +1,114 @@ +package main + +import ( + "bufio" + "flag" + "fmt" + "log" + "net" + "os" + "regexp" +) + +const ( + Version = "1.0.0" + IPRegex = `\b(?:\d{1,3}\.){3}\d{1,3}\b$` +) + +var ( + cidrFilePtr = flag.String("f", "", + "[Optional] Name of file with CIDR blocks") +) + +func main() { + flag.Usage = usage + flag.Parse() + + info, err := os.Stdin.Stat() + if err != nil { + log.Fatal(err) + } + args := os.Args[1:] + + if *cidrFilePtr != "" { + file, err := os.Open(*cidrFilePtr) + if err != nil { + log.Fatal(err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + displayIPs(scanner.Text()) + if err := scanner.Err(); err != nil { + log.Fatal(err) + } + } + } else if info.Mode()&os.ModeNamedPipe != 0 { // data is piped in + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + displayIPs(scanner.Text()) + } + } else if len(args) > 0 { // look for CIDRs on cmd line + for _, ip := range args { + displayIPs(ip) + } + } else { // no piped input, no file provide and no args, display usage + flag.Usage() + } +} + +func isIPAddr(cidr string) bool { + match, _ := regexp.MatchString(IPRegex, cidr) + return match +} + +func displayIPs(cidr string) { + var ips []string + + // if a IP address, display the IP address and return + if isIPAddr(cidr) { + fmt.Println(cidr) + return + } + + ipAddr, ipNet, err := net.ParseCIDR(cidr) + if err != nil { + log.Print(err) + return + } + + for ip := ipAddr.Mask(ipNet.Mask); ipNet.Contains(ip); increment(ip) { + ips = append(ips, ip.String()) + } + + // CIDR too small eg. /31 + if len(ips) <= 2 { + return + } + + for _, ip := range ips[1 : len(ips)-1] { + fmt.Println(ip) + } +} + +// The next IP address of a given ip address +// https://stackoverflow.com/a/33925954 +func increment(ip net.IP) { + for i := len(ip) - 1; i >= 0; i-- { + ip[i]++ + if ip[i] != 0 { + break + } + } +} + +func usage() { + fmt.Fprintf(os.Stderr, "CIDR to IPs version %s\n", Version) + fmt.Fprintf(os.Stderr, "Usage: $ cidr2ip [-f ] \n") + fmt.Fprintf(os.Stderr, "Example: $ cidr2ip -f cidrs.txt\n") + fmt.Fprintf(os.Stderr, " $ cidr2ip 10.0.0.0/24\n") + fmt.Fprintf(os.Stderr, " $ cat cidrs.txt | cidr2ip \n") + fmt.Fprintf(os.Stderr, "--------------------------\nFlags:\n") + flag.PrintDefaults() +} diff --git a/cidrs.txt b/cidrs.txt new file mode 100644 index 0000000..3606bbe --- /dev/null +++ b/cidrs.txt @@ -0,0 +1,6 @@ +# This is sample file that can be processed by cidr2ip +# Lines that do not have a CIDR block will be ignored + +127.0.0.1 +192.168.0.100/30 +10.0.0.0/29