please help me solve next task in fastest possible way
i have a large list of ip/subnets like ...
35.132.199.128/27
8.44.144.248/32
87.117.185.193
45.23.45.45
etc and i'll need to find some ip in that list fastes as possible in go.
when i try use slice of strings and range, it was very slow on large list.
may i use map, like map[string]string, and its look usable but only for ip checking, not for subnet checking.
anyone can help me with solving this task? thanks.
my code
func (app *application) validateIP(ip string) bool {
for _, item := range app.IPList {
itemIsIP := net.ParseIP(item)
if itemIsIP != nil {
if ip == itemIsIP.String() {
return true
}
continue
}
_, itemNet, err := net.ParseCIDR(item)
if err != nil {
log.Printf("[ERROR] %+v", err)
}
checkedIP := net.ParseIP(ip)
if itemNet.Contains(checkedIP) {
return true
}
}
return false
}
We solved this problem in our project:
isIPV4inCIDRList("35.132.199.128", []string{"35.132.199.128/27"})
func isIPV4inCIDRList(ip []byte, list []string) bool {
for i := 0; i < 32; i++ {
sm := strconv.Itoa(i)
m, _ := mask(sm, 4)
inv := andIP(ip, []byte(m))
if len(inv) == 0 {
continue
}
for _, cidr := range list {
if cidr == inv.String() + "/" + sm {
return true
}
}
}
return false
}
func andIP(ip, mask []byte) net.IP {
inv := net.IP{}
for i, v := range ip {
inv = append(inv, mask[i]&v)
}
return inv
}
// Bigger than we need, not too big to worry about overflow
const big = 0xFFFFFF
// Decimal to integer.
// Returns number, characters consumed, success.
func dtoi(s string) (n int, i int, ok bool) {
n = 0
for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
n = n*10 + int(s[i]-'0')
if n >= big {
return big, i, false
}
}
if i == 0 {
return 0, 0, false
}
return n, i, true
}
func mask(m string, iplen int) (net.IPMask, error) {
n, i, ok := dtoi(m)
if !ok || i != len(m) || n < 0 || n > 8*iplen {
return nil, &net.ParseError{Type: "CIDR address"}
}
return net.CIDRMask(n, 8*iplen), nil
}