// Assumes RWLock is held func (subnet *Subnet) getFreeIP() (*net.IP, bool) { bit, success := firstClearBit(subnet.ActiveBits) if success { subnet.ActiveBits.Set(bit) ip := dhcp.IPAdd(subnet.ActiveStart, int(bit)) return &ip, true } // Free invalid or expired leases save_me := false now := time.Now() for k, lease := range subnet.Leases { if now.After(lease.ExpireTime) { if dhcp.IPInRange(subnet.ActiveStart, subnet.ActiveEnd, lease.Ip) { subnet.ActiveBits.Clear(uint(dhcp.IPRange(lease.Ip, subnet.ActiveStart) - 1)) } delete(subnet.Leases, k) save_me = true } } bit, success = firstClearBit(subnet.ActiveBits) if success { subnet.ActiveBits.Set(bit) ip := dhcp.IPAdd(subnet.ActiveStart, int(bit)) return &ip, true } // We got nothin' return nil, save_me }
func (subnet *Subnet) free_lease(dt *DataTracker, nic string) { subnet.lock.Lock() lease := subnet.Leases[nic] if lease != nil { if dhcp.IPInRange(subnet.ActiveStart, subnet.ActiveEnd, lease.Ip) { subnet.ActiveBits.Clear(uint(dhcp.IPRange(lease.Ip, subnet.ActiveStart) - 1)) } delete(subnet.Leases, nic) subnet.lock.Unlock() dt.save_data() } else { subnet.lock.Unlock() } }
func (dt *DataTracker) AddBinding(subnetName string, binding Binding) (error, int) { lsubnet := dt.Subnets[subnetName] if lsubnet == nil { return errors.New("Not Found"), http.StatusNotFound } // If existing, clear the reservation for IP b := lsubnet.Bindings[binding.Mac] if b != nil { if dhcp.IPInRange(lsubnet.ActiveStart, lsubnet.ActiveEnd, b.Ip) { lsubnet.ActiveBits.Clear(uint(dhcp.IPRange(lsubnet.ActiveStart, b.Ip) - 1)) } } // Reserve the IP if in Active range if dhcp.IPInRange(lsubnet.ActiveStart, lsubnet.ActiveEnd, binding.Ip) { lsubnet.ActiveBits.Set(uint(dhcp.IPRange(lsubnet.ActiveStart, binding.Ip) - 1)) } lsubnet.Bindings[binding.Mac] = &binding dt.save_data() return nil, http.StatusOK }
func (dt *DataTracker) DeleteBinding(subnetName, mac string) (error, int) { lsubnet := dt.Subnets[subnetName] if lsubnet == nil { return errors.New("Subnet Not Found"), http.StatusNotFound } b := lsubnet.Bindings[mac] if b == nil { return errors.New("Binding Not Found"), http.StatusNotFound } if dhcp.IPInRange(lsubnet.ActiveStart, lsubnet.ActiveEnd, b.Ip) { lsubnet.ActiveBits.Clear(uint(dhcp.IPRange(lsubnet.ActiveStart, b.Ip) - 1)) } delete(lsubnet.Bindings, mac) dt.save_data() return nil, http.StatusOK }
func convertApiSubnetToSubnet(as *ApiSubnet, subnet *Subnet) (*Subnet, error) { if subnet == nil { subnet = NewSubnet() } subnet.Name = as.Name _, netdata, err := net.ParseCIDR(as.Subnet) if err != nil { return nil, err } subnet.Subnet = &MyIPNet{netdata} subnet.ActiveStart = net.ParseIP(as.ActiveStart).To4() subnet.ActiveEnd = net.ParseIP(as.ActiveEnd).To4() subnet.ActiveLeaseTime = time.Duration(as.ActiveLeaseTime) * time.Second subnet.ReservedLeaseTime = time.Duration(as.ReservedLeaseTime) * time.Second subnet.ActiveBits = bitset.New(uint(dhcp.IPRange(subnet.ActiveStart, subnet.ActiveEnd))) if as.NextServer != nil { ip := net.ParseIP(*as.NextServer).To4() subnet.NextServer = &ip } if subnet.ActiveLeaseTime == 0 { subnet.ActiveLeaseTime = 30 * time.Second } if subnet.ReservedLeaseTime == 0 { subnet.ReservedLeaseTime = 2 * time.Hour } for _, v := range as.Leases { subnet.Leases[v.Mac] = v if dhcp.IPInRange(subnet.ActiveStart, subnet.ActiveEnd, v.Ip) { subnet.ActiveBits.Set(uint(dhcp.IPRange(subnet.ActiveStart, v.Ip) - 1)) } } for _, v := range as.Bindings { subnet.Bindings[v.Mac] = v if dhcp.IPInRange(subnet.ActiveStart, subnet.ActiveEnd, v.Ip) { subnet.ActiveBits.Set(uint(dhcp.IPRange(subnet.ActiveStart, v.Ip) - 1)) } } // Seed initial options subnet.Options[dhcp.OptionSubnetMask] = []byte(net.IP(netdata.Mask).To4()) m := binary.BigEndian.Uint32(subnet.Options[dhcp.OptionSubnetMask]) n := binary.BigEndian.Uint32(netdata.IP) b := n | ^m result := make([]byte, 4) binary.BigEndian.PutUint32(result, b) subnet.Options[dhcp.OptionBroadcastAddress] = result for _, o := range as.Options { subnet.Options[o.Code], err = convertOptionValueToByte(o.Code, o.Value) if err != nil { return nil, err } } if !netdata.Contains(subnet.ActiveStart) { return nil, errors.New("ActiveStart not in Subnet") } if !netdata.Contains(subnet.ActiveEnd) { return nil, errors.New("ActiveEnd not in Subnet") } if dhcp.IPLess(subnet.ActiveEnd, subnet.ActiveStart) { return nil, errors.New("ActiveEnd less than ActiveStart") } return subnet, nil }