95 lines
1.7 KiB
Go
95 lines
1.7 KiB
Go
|
//go:build !solution
|
||
|
|
||
|
package iprange
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"net"
|
||
|
"sort"
|
||
|
)
|
||
|
|
||
|
func streamRange(lower, upper net.IP) chan net.IP {
|
||
|
ipchan := make(chan net.IP, 1)
|
||
|
|
||
|
rangeMask := net.IP([]byte{
|
||
|
upper[0] - lower[0],
|
||
|
upper[1] - lower[1],
|
||
|
upper[2] - lower[2],
|
||
|
upper[3] - lower[3],
|
||
|
})
|
||
|
|
||
|
go func() {
|
||
|
defer close(ipchan)
|
||
|
|
||
|
lower32 := binary.BigEndian.Uint32([]byte(lower))
|
||
|
upper32 := binary.BigEndian.Uint32([]byte(upper))
|
||
|
diff := upper32 - lower32
|
||
|
|
||
|
if diff < 0 {
|
||
|
panic("Lower address is actually higher than upper address.")
|
||
|
}
|
||
|
|
||
|
mask := net.IP([]byte{0, 0, 0, 0})
|
||
|
|
||
|
for {
|
||
|
ipchan <- net.IP([]byte{
|
||
|
lower[0] + mask[0],
|
||
|
lower[1] + mask[1],
|
||
|
lower[2] + mask[2],
|
||
|
lower[3] + mask[3],
|
||
|
})
|
||
|
|
||
|
if mask.Equal(rangeMask) {
|
||
|
break
|
||
|
}
|
||
|
|
||
|
for i := 3; i >= 0; i-- {
|
||
|
if rangeMask[i] > 0 {
|
||
|
if mask[i] < rangeMask[i] {
|
||
|
mask[i] = mask[i] + 1
|
||
|
break
|
||
|
} else {
|
||
|
mask[i] = mask[i] % rangeMask[i]
|
||
|
if i < 1 {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}()
|
||
|
|
||
|
return ipchan
|
||
|
}
|
||
|
|
||
|
// Expand expands an address with a mask taken from a stream
|
||
|
func (r *AddressRange) Expand() []net.IP {
|
||
|
ips := []net.IP{}
|
||
|
for ip := range streamRange(r.Min, r.Max) {
|
||
|
ips = append(ips, ip)
|
||
|
}
|
||
|
return ips
|
||
|
}
|
||
|
|
||
|
// Expand expands and normalizes a set of parsed target specifications
|
||
|
func (l AddressRangeList) Expand() []net.IP {
|
||
|
var res []net.IP
|
||
|
for i := range l {
|
||
|
res = append(res, l[i].Expand()...)
|
||
|
}
|
||
|
return normalize(res)
|
||
|
}
|
||
|
|
||
|
func normalize(src []net.IP) []net.IP {
|
||
|
sort.Sort(asc(src))
|
||
|
dst := make([]net.IP, 1, len(src))
|
||
|
dst[0] = src[0]
|
||
|
for i := range src {
|
||
|
if !dst[len(dst)-1].Equal(src[i]) {
|
||
|
dst = append(dst, src[i])
|
||
|
}
|
||
|
}
|
||
|
return dst
|
||
|
}
|