Skip to content

Commit

Permalink
Merge pull request #76 from rm-Umar/master
Browse files Browse the repository at this point in the history
Added --unique, -u for randip
  • Loading branch information
UmanShahzad authored Nov 19, 2021
2 parents 5d6a090 + 291b090 commit 0385085
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 21 deletions.
8 changes: 8 additions & 0 deletions ipinfo/cmd_randip.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ var completionsRandIP = &complete.Command{
"--end": predict.Nothing,
"-x": predict.Nothing,
"--exclude-reserved": predict.Nothing,
"-u": predict.Nothing,
"--unique": predict.Nothing,
},
}

Expand All @@ -43,11 +45,15 @@ Description:
between range of :: to ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff.
Note that only IPv4 or IPv6 IPs can be generated, but not both.
When generating unique IPs, the range size must not be less than the desired
number of random IPs.
$ %[1]s randip
$ %[1]s randip --ipv6 --num 5
$ %[1]s randip -4 -n 10
$ %[1]s randip -4 -s 1.1.1.1 -e 10.10.10.10
$ %[1]s randip -4 -s 1.1.1.1 -e 10.10.10.10 -n 5 -u
$ %[1]s randip -6 --start 9c61:f71e:656d:d12e:98a3:9814:38cf:5592
$ %[1]s randip -6 --end eedd:8977:56d9:aac3:947b:29cc:78ea:deab
Expand All @@ -69,6 +75,8 @@ Options:
--exclude-reserved, -x
exclude reserved/bogon IPs.
full list can be found at https://ipinfo.io/bogon.
--unique, -u
generate unique IPs.
`, progBase)
}

Expand Down
10 changes: 8 additions & 2 deletions lib/cmd_randip.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type CmdRandIPFlags struct {
IPv4 bool
IPv6 bool
ExcludeRes bool
Unique bool
StartIP string
EndIP string
}
Expand Down Expand Up @@ -49,6 +50,11 @@ func (f *CmdRandIPFlags) Init() {
"exclude-reserved", "x", false,
"exclude reserved/bogon IPs.",
)
pflag.BoolVarP(
&f.Unique,
"unique", "u", false,
"generates only unique IPs.",
)
pflag.StringVarP(
&f.StartIP,
"start", "s", "",
Expand Down Expand Up @@ -81,7 +87,7 @@ func CmdRandIP(f CmdRandIPFlags, args []string, printHelp func()) error {
if f.EndIP == "" {
f.EndIP = "255.255.255.255"
}
if err := RandIP4RangeListWrite(f.StartIP, f.EndIP, f.N, f.ExcludeRes); err != nil {
if err := RandIP4RangeListWrite(f.StartIP, f.EndIP, f.N, f.ExcludeRes, f.Unique); err != nil {
return err
}
} else if f.IPv6 {
Expand All @@ -91,7 +97,7 @@ func CmdRandIP(f CmdRandIPFlags, args []string, printHelp func()) error {
if f.EndIP == "" {
f.EndIP = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
}
if err := RandIP6RangeListWrite(f.StartIP, f.EndIP, f.N, f.ExcludeRes); err != nil {
if err := RandIP6RangeListWrite(f.StartIP, f.EndIP, f.N, f.ExcludeRes, f.Unique); err != nil {
return err
}
}
Expand Down
90 changes: 76 additions & 14 deletions lib/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,12 @@ func RandIP4Range(iprange IP4Range, noBogon bool) (net.IP, error) {
}

// get random IP and adjust it to fit range.
randIP := binary.BigEndian.Uint32(RandIP4(noBogon).To4())
randIP %= (uint32(iprange.endIP) - uint32(iprange.startIP))
randIP += uint32(iprange.startIP)
var randIP uint64
randIP = uint64(binary.BigEndian.Uint32(RandIP4(noBogon).To4()))
randIP %= (uint64(iprange.endIP) - uint64(iprange.startIP)) + 1
randIP += uint64(iprange.startIP)
randIPbyte := [4]byte{0, 0, 0, 0}
binary.BigEndian.PutUint32(randIPbyte[:], randIP)
binary.BigEndian.PutUint32(randIPbyte[:], uint32(randIP))
return net.IP(randIPbyte[:]), nil
}

Expand All @@ -157,22 +158,47 @@ func RandIP4ListWrite(n int, noBogon bool) {
// `startIP` and `endIP` are the start & end IPs to generate IPs between.
// `n` is the number of IPs to generate.
// `noBogon`, if true, will ensure that none of the generated IPs are bogons.
// `unique`, if true, will ensure every IP generated is unique.
func RandIP4RangeListWrite(
startIP string,
endIP string,
n int,
noBogon bool,
unique bool,
) error {
ipRange, err := NewIP4Range(startIP, endIP)
if err != nil {
return err
}
for i := 0; i < n; i++ {
ip, err := RandIP4Range(ipRange, noBogon)
if err != nil {
return err
if unique {
// ensure range is larger than number of IPs to generate.
if uint64(uint64(ipRange.endIP)-uint64(ipRange.startIP)+1) < uint64(n) {
return errors.New("range is too small for unique IPs")
}

uniqueIP := make(map[uint32]struct{})
for i := 0; i < n; i++ {
unique:
ip, err := RandIP4Range(ipRange, noBogon)
if err != nil {
return err
}
// does IP already exist? if so try again.
ipInt := binary.BigEndian.Uint32(ip)
if _, ok := uniqueIP[ipInt]; ok {
goto unique
}
uniqueIP[ipInt] = struct{}{}
fmt.Println(ip)
}
} else {
for i := 0; i < n; i++ {
ip, err := RandIP4Range(ipRange, noBogon)
if err != nil {
return err
}
fmt.Println(ip)
}
fmt.Println(ip)
}
return nil
}
Expand Down Expand Up @@ -215,6 +241,7 @@ func RandIP6Range(ipRange IP6RangeInt, noBogon bool) net.IP {
copy(randIPBytes[16-len(randIPBigIntBytes):], randIPBigIntBytes)
return net.IP(randIPBytes[:]).To16()
}
tmp.Add(tmp, big.NewInt(1))
randIP.Mod(randIP, tmp)
randIP.Add(randIP, ipRange.startIP)
// convert multi-precision byte form into 16-byte IPv6 form.
Expand All @@ -240,15 +267,50 @@ func RandIP6ListWrite(n int, noBogon bool) {
}
}

// RandIP6ListWrite prints a list of new randomly generated IPv6 addresses
// withing starting and ending IPs range.
func RandIP6RangeListWrite(startIP, endIP string, n int, noBogon bool) error {
// RandIP6RangeListWrite prints a list of randomly generated IPv6 addresses.
// `startIP` and `endIP` are the start & end IPs to generate IPs between.
// `n` is the number of IPs to generate.
// `noBogon`, if true, will ensure that none of the generated IPs are bogons.
// `unique`, if true, will ensure every IP generated is unique.
func RandIP6RangeListWrite(
startIP string,
endIP string,
n int,
noBogon bool,
unique bool,
) error {
ipRange, err := NewIP6RangeInt(startIP, endIP)
if err != nil {
return err
}
for i := 0; i < n; i++ {
fmt.Println(RandIP6Range(ipRange, noBogon))
if unique {
// ensure range is larger than number of IPs to generate.
tmp := new(big.Int)
tmp.Sub(ipRange.endIP, ipRange.startIP)
tmp.Add(tmp, big.NewInt(1))
count := new(big.Int).SetUint64(uint64(n))
if tmp.Cmp(count) < 0 {
return errors.New("range is too small for unique IPs")
}

uniqueIP := make(map[IP6]struct{})
for i := 0; i < n; i++ {
unique:
ip := RandIP6Range(ipRange, noBogon)
var ipInt IP6
ipInt.N.Hi = binary.BigEndian.Uint64(ip[0:])
ipInt.N.Lo = binary.BigEndian.Uint64(ip[8:])
// does IP already exist? if so try again.
if _, ok := uniqueIP[ipInt]; ok {
goto unique
}
uniqueIP[ipInt] = struct{}{}
fmt.Println(ip)
}
} else {
for i := 0; i < n; i++ {
fmt.Println(RandIP6Range(ipRange, noBogon))
}
}
return nil
}
Expand Down
17 changes: 12 additions & 5 deletions randip/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@ Description:
Note that only IPv4 or IPv6 IPs can be generated, but not both.
$ %[1]s --ipv6 --num 5
$ %[1]s -4 -n 10
$ %[1]s -4 -s 1.1.1.1 -e 10.10.10.10
$ %[1]s -6 --start 9c61:f71e:656d:d12e:98a3:9814:38cf:5592
$ %[1]s -6 --end eedd:8977:56d9:aac3:947b:29cc:78ea:deab
When generating unique IPs, the range size must not be less than the desired
number of random IPs.
$ %[1]s
$ %[1]s --ipv6 --num 5
$ %[1]s -4 -n 10
$ %[1]s -4 -s 1.1.1.1 -e 10.10.10.10
$ %[1]s -4 -s 1.1.1.1 -e 10.10.10.10 -n 5 -u
$ %[1]s -6 --start 9c61:f71e:656d:d12e:98a3:9814:38cf:5592
$ %[1]s -6 --end eedd:8977:56d9:aac3:947b:29cc:78ea:deab
Options:
--help, -h
Expand All @@ -54,6 +59,8 @@ Options:
--exclude-reserved, -x
exclude reserved/bogon IPs.
full list can be found at https://ipinfo.io/bogon.
--unique, -u
generate unique IPs.
Completions:
--completions-install
Expand Down

0 comments on commit 0385085

Please sign in to comment.