Skip to content

Commit

Permalink
Merge pull request #100 from projectdiscovery/dev
Browse files Browse the repository at this point in the history
IP Range input support
  • Loading branch information
ehsandeep authored Sep 12, 2022
2 parents d3d48b7 + 835671e commit 8f1979e
Show file tree
Hide file tree
Showing 10 changed files with 445 additions and 62 deletions.
20 changes: 11 additions & 9 deletions .github/workflows/release-binary.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: 🎉 Release Binary

on:
create:
tags:
Expand All @@ -8,23 +9,24 @@ on:
jobs:
release:
runs-on: ubuntu-latest
steps:
-
name: "Check out code"
steps:
- name: "Check out code"
uses: actions/checkout@v3
with:
fetch-depth: 0
-
name: "Set up Go"

- name: "Set up Go"
uses: actions/setup-go@v3
with:
with:
go-version: 1.18
-
env:

- env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
SLACK_WEBHOOK: "${{ secrets.RELEASE_SLACK_WEBHOOK }}"

name: "Create release on GitHub"
uses: goreleaser/goreleaser-action@v3
with:
with:
args: "release --rm-dist"
version: latest
workdir: .
9 changes: 8 additions & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,11 @@ archives:
darwin: macOS
format_overrides:
- goos: windows
format: zip
format: zip

announce:
slack:
enabled: true
channel: '#release'
username: GoReleaser
message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.18.3-alpine AS build-env
FROM golang:1.19.1-alpine AS build-env
RUN go install -v github.com/projectdiscovery/mapcidr/cmd/mapcidr@latest

FROM alpine:latest
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@ mapcidr -cidr 173.0.84.0/24
173.0.84.16
```

It is also possible to get list of IP's for a given IP range, use the following command
```console
$ echo "192.168.0.0-192.168.0.5" | mapcidr
```
```console
192.168.0.0
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5
```
### CIDR Slicing by CIDR Count

In order to slice given CIDR or list of CIDR by CIDR count or slice into multiple and equal smaller subnets, use the following command.
Expand Down Expand Up @@ -199,6 +211,23 @@ $ cat ips.txt | mapcidr -aggregate-approx
1.1.1.0/27
```

In order to list CIDR blocks for given IP Range (**IPv4 | IPv6**), use the following command.
```
$ mapcidr -cl 192.168.0.1-192.168.0.255 -aggregate
OR
$ echo 192.168.0.1-192.168.0.255 | mapcidr -aggregate
```
```
192.168.0.1/32
192.168.0.2/31
192.168.0.4/30
192.168.0.8/29
192.168.0.16/28
192.168.0.32/27
192.168.0.64/26
192.168.0.128/25
```
### Match / Filter IP's from CIDR

In order to match IPs from the given list of CIDR ranges, use the following command.
Expand Down
106 changes: 74 additions & 32 deletions cmd/mapcidr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ func ParseOptions() *Options {
flagSet.BoolVar(&options.Version, "version", false, "Show version of the project"),
)

_ = flagSet.Parse()
if err := flagSet.Parse(); err != nil {
gologger.Fatal().Msgf("%s\n", err)
}

// Read the inputs and configure the logging
options.configureOutput()
Expand Down Expand Up @@ -281,16 +283,31 @@ func prepareIPsFromCidrFlagList(items []string) []string {
func process(wg *sync.WaitGroup, chancidr, outputchan chan string) {
defer wg.Done()
var (
allCidrs []*net.IPNet
pCidr *net.IPNet
ranger *ipranger.IPRanger
err error
hasSort = options.SortAscending || options.SortDescending
allCidrs []*net.IPNet
pCidr *net.IPNet
ranger *ipranger.IPRanger
err error
hasSort = options.SortAscending || options.SortDescending
ipRangeList = make([][]net.IP, 0)
)

ranger, _ = ipranger.New()

for cidr := range chancidr {

// Add IPs into ipRangeList which are passed as input. Example - "192.168.0.0-192.168.0.5"
if strings.Contains(cidr, "-") {
var ipRange []net.IP
for _, ipstr := range strings.Split(cidr, "-") {
ipRange = append(ipRange, net.ParseIP(ipstr))
}
//check if ipRange has more than 2 values
if len(ipRange) > 2 {
gologger.Fatal().Msgf("IP range can not have more than 2 values.")
}
ipRangeList = append(ipRangeList, ipRange)
continue
}
// if it's an ip turn it into a cidr
if ip := net.ParseIP(cidr); ip != nil {
switch {
Expand All @@ -316,34 +333,23 @@ func process(wg *sync.WaitGroup, chancidr, outputchan chan string) {

// In case of coalesce/shuffle we need to know all the cidrs and aggregate them by calling the proper function
if options.Aggregate || options.Shuffle || hasSort || options.AggregateApprox || options.Count {
_ = ranger.AddIPNet(pCidr)
_ = ranger.Add(cidr)
allCidrs = append(allCidrs, pCidr)
} else if options.Slices > 0 {
subnets, err := mapcidr.SplitN(cidr, options.Slices)
if err != nil {
gologger.Fatal().Msgf("%s\n", err)
}
for _, subnet := range subnets {
outputchan <- subnet.String()
}
} else if options.HostCount > 0 {
subnets, err := mapcidr.SplitByNumber(cidr, options.HostCount)
if err != nil {
gologger.Fatal().Msgf("%s\n", err)
}
for _, subnet := range subnets {
outputchan <- subnet.String()
}
} else {
var ipFlagList []string
ipFlagList = append(ipFlagList, prepareIPsFromCidrFlagList(options.MatchIP)...)
ipFlagList = append(ipFlagList, prepareIPsFromCidrFlagList(options.FilterIP)...)
ips, err := mapcidr.IPAddressesAsStream(cidr)
if err != nil {
gologger.Fatal().Msgf("%s\n", err)
}
for ip := range ips {
filterIPsFromFlagList(outputchan, ip, ipFlagList)
commonFunc(cidr, outputchan)
}
}

for _, ipRange := range ipRangeList {
cidrs, err := mapcidr.GetCIDRFromIPRange(ipRange[0], ipRange[1])
if err != nil {
gologger.Fatal().Msgf("%s\n", err)
}
if options.Aggregate || options.Shuffle || hasSort || options.AggregateApprox || options.Count {
allCidrs = append(allCidrs, cidrs...)
} else {
for _, cidr := range cidrs {
commonFunc(cidr.String(), outputchan)
}
}
}
Expand Down Expand Up @@ -413,6 +419,42 @@ func process(wg *sync.WaitGroup, chancidr, outputchan chan string) {
close(outputchan)
}

/*
The purpose of the function is split into subnets or split by no. of host or CIDR expansion.
This gives us benefit of DRY and we can add new features here going forward.
*/
func commonFunc(cidr string, outputchan chan string) {
if options.Slices > 0 {
subnets, err := mapcidr.SplitN(cidr, options.Slices)
if err != nil {
gologger.Fatal().Msgf("%s\n", err)
}
for _, subnet := range subnets {
outputchan <- subnet.String()
}
} else if options.HostCount > 0 {
subnets, err := mapcidr.SplitByNumber(cidr, options.HostCount)
if err != nil {
gologger.Fatal().Msgf("%s\n", err)
}
for _, subnet := range subnets {
outputchan <- subnet.String()
}
} else {
var ipFlagList []string
ipFlagList = append(ipFlagList, prepareIPsFromCidrFlagList(options.MatchIP)...)
ipFlagList = append(ipFlagList, prepareIPsFromCidrFlagList(options.FilterIP)...)

ips, err := mapcidr.IPAddressesAsStream(cidr)
if err != nil {
gologger.Fatal().Msgf("%s\n", err)
}
for ip := range ips {
filterIPsFromFlagList(outputchan, ip, ipFlagList)
}
}
}

func output(wg *sync.WaitGroup, outputchan chan string) {
defer wg.Done()

Expand Down
Loading

0 comments on commit 8f1979e

Please sign in to comment.