-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathipnetgen.go
67 lines (56 loc) · 1.4 KB
/
ipnetgen.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package ipnetgen
import (
"math/big"
"net"
)
//Increment increments the given net.IP by one bit. Incrementing the last IP in an IP space (IPv4, IPV6) is undefined.
func Increment(ip net.IP) {
for i := len(ip) - 1; i >= 0; i-- {
ip[i]++
//only add to the next byte if we overflowed
if ip[i] != 0 {
break
}
}
}
//IPNetGenerator is a net.IPnet wrapper that you can iterate over
type IPNetGenerator struct {
*net.IPNet
count *big.Int
//state
idx *big.Int
current net.IP
}
//New creates a new IPNetGenerator from a CIDR string, or an error if the CIDR is invalid.
func New(cidr string) (*IPNetGenerator, error) {
_, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
return nil, err
}
return NewFromIPNet(ipNet), nil
}
//NewFromIPNet creates a new IPNetGenerator from a *net.IPNet
func NewFromIPNet(ipNet *net.IPNet) *IPNetGenerator {
ones, bits := ipNet.Mask.Size()
newIP := make(net.IP, len(ipNet.IP))
copy(newIP, ipNet.IP)
count := big.NewInt(0)
count.Exp(big.NewInt(2), big.NewInt(int64(bits-ones)), nil)
return &IPNetGenerator{
IPNet: ipNet,
count: count,
idx: big.NewInt(0),
current: newIP,
}
}
//Next returns the next net.IP in the subnet
func (g *IPNetGenerator) Next() net.IP {
g.idx.Add(g.idx, big.NewInt(1))
if g.idx.Cmp(g.count) == 1 {
return nil
}
current := make(net.IP, len(g.current))
copy(current, g.current)
Increment(g.current)
return current
}