// return an available ip if one is currently available. If not, // return the next available ip for the nextwork func (allocated *allocatedMap) getNextIP(network *net.IPNet) (*net.IP, error) { var ( ownIP = ipToInt(&network.IP) first, _ = networkdriver.NetworkRange(network) base = ipToInt(&first) size = int(networkdriver.NetworkSize(network.Mask)) max = int32(size - 2) // size -1 for the broadcast network, -1 for the gateway network pos = allocated.last ) var ( firstNetIP = network.IP.To4().Mask(network.Mask) firstAsInt = ipToInt(&firstNetIP) + 1 ) for i := int32(0); i < max; i++ { pos = pos%max + 1 next := int32(base + pos) if next == ownIP || next == firstAsInt { continue } if _, ok := allocated.p[pos]; ok { continue } allocated.p[pos] = struct{}{} allocated.last = pos return intToIP(next), nil } return nil, ErrNoAvailableIPs }
func newAllocatedMap(network *net.IPNet) *allocatedMap { firstIP, lastIP := networkdriver.NetworkRange(network) begin := ipToInt(firstIP) + 2 end := ipToInt(lastIP) - 1 return &allocatedMap{ p: make(map[uint32]struct{}), begin: begin, end: end, last: begin - 1, // so first allocated will be begin } }
func newAllocatedMap(network *net.IPNet) *allocatedMap { firstIP, lastIP := networkdriver.NetworkRange(network) begin := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1)) end := big.NewInt(0).Sub(ipToBigInt(lastIP), big.NewInt(1)) return &allocatedMap{ p: make(map[string]struct{}), begin: begin, end: end, last: big.NewInt(0).Sub(begin, big.NewInt(1)), // so first allocated will be begin } }
func newAllocatedMap(network *net.IPNet) *allocatedMap { firstIP, lastIP := networkdriver.NetworkRange(network) begin := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1)) end := big.NewInt(0).Sub(ipToBigInt(lastIP), big.NewInt(1)) // if IPv4 network, then allocation range starts at begin + 1 because begin is bridge IP if len(firstIP) == 4 { begin = begin.Add(begin, big.NewInt(1)) } return &allocatedMap{ p: make(map[string]struct{}), begin: begin, end: end, last: big.NewInt(0).Sub(begin, big.NewInt(1)), // so first allocated will be begin } }
// RegisterSubnet registers network in global allocator with bounds // defined by subnet. If you want to use network range you must call // this method before first RequestIP, otherwise full network range will be used func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error { lock.Lock() defer lock.Unlock() key := network.String() if _, ok := allocatedIPs[key]; ok { return ErrNetworkAlreadyRegistered } n := newAllocatedMap(network) beginIP, endIP := networkdriver.NetworkRange(subnet) begin, end := ipToInt(beginIP)+1, ipToInt(endIP)-1 if !(begin >= n.begin && end <= n.end && begin < end) { return ErrBadSubnet } n.begin = begin n.end = end n.last = begin - 1 allocatedIPs[key] = n return nil }
// RegisterSubnet registers network in global allocator with bounds // defined by subnet. If you want to use network range you must call // this method before first RequestIP, otherwise full network range will be used func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error { lock.Lock() defer lock.Unlock() key := network.String() if _, ok := allocatedIPs[key]; ok { return ErrNetworkAlreadyRegistered } n := newAllocatedMap(network) beginIP, endIP := networkdriver.NetworkRange(subnet) begin := big.NewInt(0).Add(ipToBigInt(beginIP), big.NewInt(1)) end := big.NewInt(0).Sub(ipToBigInt(endIP), big.NewInt(1)) // Check that subnet is within network if !(begin.Cmp(n.begin) >= 0 && end.Cmp(n.end) <= 0 && begin.Cmp(end) == -1) { return ErrBadSubnet } n.begin.Set(begin) n.end.Set(end) n.last.Sub(begin, big.NewInt(1)) allocatedIPs[key] = n return nil }
// convert the ip into the position in the subnet. Only // position are saved in the set func getPosition(network *net.IPNet, ip *net.IP) int32 { first, _ := networkdriver.NetworkRange(network) return ipToInt(ip) - ipToInt(&first) }