Example #1
0
// 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
}
Example #2
0
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()
	}
}
Example #3
0
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
}
Example #4
0
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
}
Example #5
0
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
}