2020-09-28 00:49:58 +08:00
|
|
|
package dhcpd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
2020-09-29 00:38:35 +08:00
|
|
|
"math/rand"
|
2020-09-28 00:49:58 +08:00
|
|
|
"net"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Pool struct {
|
|
|
|
items []*item
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPool(lease time.Duration, ipStart, ipEnd net.IP) (*Pool, error) {
|
|
|
|
items := make([]*item, 0)
|
2020-09-29 00:38:35 +08:00
|
|
|
curip := ipStart.To4()
|
|
|
|
for bytes.Compare(curip, ipEnd.To4()) <= 0 {
|
2020-09-28 00:49:58 +08:00
|
|
|
ip := make([]byte, 4)
|
2020-09-29 00:38:35 +08:00
|
|
|
copy(ip, curip)
|
|
|
|
items = append(items, &item{lease: lease, ip: ip})
|
|
|
|
curip[3]++
|
2020-09-28 00:49:58 +08:00
|
|
|
}
|
2020-09-29 00:38:35 +08:00
|
|
|
rand.Seed(time.Now().Unix())
|
|
|
|
return &Pool{items: items}, nil
|
2020-09-28 00:49:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Pool) AssignIP(mac net.HardwareAddr) (net.IP, error) {
|
|
|
|
var ip net.IP
|
|
|
|
for _, item := range p.items {
|
2020-09-29 00:38:35 +08:00
|
|
|
if bytes.Equal(mac, item.mac) {
|
2020-09-28 00:49:58 +08:00
|
|
|
return item.ip, nil
|
|
|
|
}
|
|
|
|
}
|
2020-09-29 00:38:35 +08:00
|
|
|
|
|
|
|
idx := rand.Intn(len(p.items))
|
|
|
|
for _, item := range p.items[idx:] {
|
|
|
|
if ip = item.take(mac); ip != nil {
|
|
|
|
return ip, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-28 00:49:58 +08:00
|
|
|
for _, item := range p.items {
|
|
|
|
if ip = item.take(mac); ip != nil {
|
|
|
|
return ip, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, errors.New("no more ip can be assigned")
|
|
|
|
}
|
|
|
|
|
|
|
|
type item struct {
|
2020-09-29 00:38:35 +08:00
|
|
|
taken bool
|
|
|
|
ip net.IP
|
|
|
|
lease time.Duration
|
|
|
|
mac net.HardwareAddr
|
2020-09-28 00:49:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *item) take(addr net.HardwareAddr) net.IP {
|
2020-09-29 00:38:35 +08:00
|
|
|
if !i.taken {
|
2020-09-28 00:49:58 +08:00
|
|
|
i.taken = true
|
|
|
|
go func() {
|
|
|
|
timer := time.NewTimer(i.lease)
|
|
|
|
<-timer.C
|
2020-09-29 00:38:35 +08:00
|
|
|
i.mac = nil
|
2020-09-28 00:49:58 +08:00
|
|
|
i.taken = false
|
|
|
|
}()
|
2020-09-29 00:38:35 +08:00
|
|
|
i.mac = addr
|
2020-09-28 00:49:58 +08:00
|
|
|
return i.ip
|
|
|
|
}
|
2020-09-29 00:38:35 +08:00
|
|
|
return nil
|
2020-09-28 00:49:58 +08:00
|
|
|
}
|