// convert the ip into the position in the subnet. Only // position are saved in the set func getPosition(address *net.IPNet, ip *net.IP) int32 { var ( first, _ = networkdriver.NetworkRange(address) base = ipToInt(&first) i = ipToInt(ip) ) return i - base }
// return an available ip if one is currently available. If not, // return the next available ip for the nextwork func getNextIp(address *net.IPNet) (*net.IP, error) { var ( ownIP = ipToInt(&address.IP) available = availableIPS[address.String()] allocated = allocatedIPs[address.String()] first, _ = networkdriver.NetworkRange(address) base = ipToInt(&first) size = int(networkdriver.NetworkSize(address.Mask)) max = int32(size - 2) // size -1 for the broadcast address, -1 for the gateway address pos = int32(available.Pop()) ) // We pop and push the position not the ip if pos != 0 { ip := intToIP(int32(base + pos)) allocated.Push(int(pos)) return ip, nil } var ( firstNetIP = address.IP.To4().Mask(address.Mask) firstAsInt = ipToInt(&firstNetIP) + 1 ) pos = int32(allocated.PullBack()) for i := int32(0); i < max; i++ { pos = pos%max + 1 next := int32(base + pos) if next == ownIP || next == firstAsInt { continue } if !allocated.Exists(int(pos)) { ip := intToIP(next) allocated.Push(int(pos)) return ip, nil } } return nil, ErrNoAvailableIPs }