package ipfunc import ( "errors" "fmt" "net" "sync" ) type IPSubnet struct { freeIPs []string mux sync.Mutex } func NewIPSubnet(network string) (IPSubnet, error) { i := IPSubnet{} ip, ipnet, err := net.ParseCIDR(network) if err != nil { return IPSubnet{}, fmt.Errorf("Cant create IPSubnet, input ip cant pase: %w", err) } var ips []string for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) { ips = append(ips, ip.String()) } lenIPs := len(ips) switch { case lenIPs < 2: i.freeIPs = ips default: i.freeIPs = ips[1 : len(ips)-1] } return i, nil } func (i *IPSubnet) GetNextFreeIP() (string, error) { if len(i.freeIPs) == 0 { return "", errors.New("No free IP") } i.mux.Lock() defer i.mux.Unlock() rip := i.freeIPs[0] i.remove(rip) return rip, nil } func (i *IPSubnet) remove (ip string) { var newips []string for _, oneIp := range i.freeIPs { if oneIp != ip { newips = append(newips, oneIp) } } i.freeIPs = newips } func (i *IPSubnet)Remove(ip string) { i.mux.Lock() defer i.mux.Unlock() i.remove(ip) } func inc(ip net.IP) { for j := len(ip) - 1; j >= 0; j-- { ip[j]++ if ip[j] > 0 { break } } }