43 lines
909 B
Go
43 lines
909 B
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
"math/big"
|
|
"net"
|
|
)
|
|
|
|
func iptouint(ip net.IP) uint32 {
|
|
ip = ip.To4()
|
|
return uint32(ip[0])<<24 | uint32(ip[1])<<16 | uint32(ip[2])<<8 | uint32(ip[3])
|
|
}
|
|
|
|
func toip(num uint32) string {
|
|
return fmt.Sprintf("%d.%d.%d.%d",
|
|
(num>>24)&255,
|
|
(num>>16)&255,
|
|
(num>>8)&255,
|
|
num&255)
|
|
}
|
|
|
|
// per-cidr linear congruential generator for efficient randomized target ip ordering, ty claude
|
|
func lcgcidr(cidr string, out chan<- string) {
|
|
// lcg constants
|
|
const a uint64 = 1664525
|
|
const c uint64 = 1013904223
|
|
|
|
_, ipnet, _ := net.ParseCIDR(cidr)
|
|
start := iptouint(ipnet.IP)
|
|
|
|
ones, bits := ipnet.Mask.Size()
|
|
addrcount := new(big.Int).Lsh(big.NewInt(1), uint(bits-ones))
|
|
|
|
x := uint64(start)
|
|
m := uint64(addrcount.Uint64())
|
|
|
|
for i := uint64(0); i < m; i++ {
|
|
x = (a*x + c) % (1 << 32) // mod of full 32bit addr count
|
|
ip := toip(uint32((x % m) + uint64(start)))
|
|
out <- ip
|
|
}
|
|
}
|