working on adding lease handouts
This commit is contained in:
@@ -5,6 +5,8 @@ go_library(
|
||||
srcs = [
|
||||
"ifi.go",
|
||||
"ifi_linux.go",
|
||||
"lease_state.go",
|
||||
"pools.go",
|
||||
"server.go",
|
||||
],
|
||||
importpath = "git.wntrmute.dev/kyle/kdhcp/server",
|
||||
@@ -12,6 +14,8 @@ go_library(
|
||||
deps = [
|
||||
"//config",
|
||||
"//dhcp",
|
||||
"//iptools",
|
||||
"@dev_wntrmute_git_kyle_goutils//syslog",
|
||||
"@in_gopkg_yaml_v2//:yaml_v2",
|
||||
],
|
||||
)
|
||||
|
||||
62
server/lease_state.go
Normal file
62
server/lease_state.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
log "git.wntrmute.dev/kyle/goutils/syslog"
|
||||
"git.wntrmute.dev/kyle/kdhcp/iptools"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type LeaseState struct {
|
||||
Pools map[string]*iptools.Pool `yaml:"pools"`
|
||||
Static map[string]*iptools.LeaseInfo `yaml:"static"`
|
||||
}
|
||||
|
||||
func (srv *Server) SaveLeases() error {
|
||||
leaseFile, err := os.Create(srv.Config.LeaseFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("server: while saving leases: %w", err)
|
||||
}
|
||||
defer leaseFile.Close()
|
||||
encoder := yaml.NewEncoder(leaseFile)
|
||||
|
||||
state := &LeaseState{
|
||||
Pools: srv.Pools,
|
||||
Static: srv.Static,
|
||||
}
|
||||
|
||||
if err = encoder.Encode(state); err != nil {
|
||||
return fmt.Errorf("server: while saving leases: %w", err)
|
||||
}
|
||||
|
||||
if err = encoder.Close(); err != nil {
|
||||
return fmt.Errorf("server: while saving leases: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (srv *Server) LoadLeases() error {
|
||||
leaseState := &LeaseState{}
|
||||
leaseFile, err := os.Open(srv.Config.LeaseFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
log.Warningf("server: not loading leases from %s: lease file not found", srv.Config.LeaseFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("server: while reading leases: %w", err)
|
||||
}
|
||||
defer leaseFile.Close()
|
||||
decoder := yaml.NewDecoder(leaseFile)
|
||||
|
||||
if err = decoder.Decode(leaseState); err != nil {
|
||||
return fmt.Errorf("server: while reading leases: %w", err)
|
||||
}
|
||||
|
||||
srv.Pools = leaseState.Pools
|
||||
srv.Static = leaseState.Static
|
||||
return nil
|
||||
}
|
||||
37
server/pools.go
Normal file
37
server/pools.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
|
||||
log "git.wntrmute.dev/kyle/goutils/syslog"
|
||||
"git.wntrmute.dev/kyle/kdhcp/iptools"
|
||||
)
|
||||
|
||||
// pools.go adds pool functionality to the server.
|
||||
|
||||
func (srv *Server) loadPoolsFromConfig() error {
|
||||
for host, ip := range srv.Config.Statics {
|
||||
addr, ok := netip.AddrFromSlice(ip.To4())
|
||||
if !ok {
|
||||
return fmt.Errorf("server: while instantiating pools, could not load IP %s", ip)
|
||||
}
|
||||
log.Debugf("server: added static host entry %s -> %s", host, addr)
|
||||
srv.Static[host] = &iptools.LeaseInfo{
|
||||
HostName: host,
|
||||
Addr: addr,
|
||||
}
|
||||
}
|
||||
|
||||
for name, ipRange := range srv.Config.Pools {
|
||||
pool, err := iptools.NewPool(name, ipRange)
|
||||
if err != nil {
|
||||
return fmt.Errorf("server: couldn't load pool %s: %w", name, err)
|
||||
}
|
||||
log.Debugf("server: added pool %s: %s -> %s", name, ipRange.Start, ipRange.End)
|
||||
|
||||
srv.Pools[name] = pool
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -3,19 +3,25 @@ package server
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
log "git.wntrmute.dev/kyle/goutils/syslog"
|
||||
"git.wntrmute.dev/kyle/kdhcp/config"
|
||||
"git.wntrmute.dev/kyle/kdhcp/dhcp"
|
||||
"git.wntrmute.dev/kyle/kdhcp/iptools"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxPacketSize = 512
|
||||
DefaultPool = "default"
|
||||
MaxPacketSize = 512
|
||||
MaxResponseWait = 5 * time.Minute
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Conn net.PacketConn
|
||||
Config *config.Config
|
||||
Pools map[string]*iptools.Pool
|
||||
Static map[string]*iptools.LeaseInfo
|
||||
}
|
||||
|
||||
func (s *Server) Close() error {
|
||||
@@ -24,6 +30,8 @@ func (s *Server) Close() error {
|
||||
|
||||
func (s *Server) Bind() (err error) {
|
||||
// In order to read DHCP packets, we'll need to listen on all addresses.
|
||||
// That being said, we also want to limit our listening to the DHCP
|
||||
// network device.
|
||||
ip := net.IP([]byte{0, 0, 0, 0})
|
||||
s.Conn, err = BindInterface(ip, s.Config.Port, s.Config.Interface)
|
||||
return err
|
||||
@@ -46,7 +54,7 @@ func (s *Server) ReadDHCPRequest() (*dhcp.BootRequest, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("server: read %db packet from %s", len(pkt), addr)
|
||||
log.Debugf("server: read packet from %s", addr)
|
||||
return dhcp.ReadRequest(pkt)
|
||||
}
|
||||
|
||||
@@ -77,10 +85,19 @@ func (s *Server) Listen() {
|
||||
func New(cfg *config.Config) (*Server, error) {
|
||||
srv := &Server{
|
||||
Config: cfg,
|
||||
Pools: map[string]*iptools.Pool{},
|
||||
Static: map[string]*iptools.LeaseInfo{},
|
||||
}
|
||||
|
||||
err := srv.Bind()
|
||||
if err != nil {
|
||||
if err := srv.loadPoolsFromConfig(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := srv.LoadLeases(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := srv.Bind(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -88,3 +105,19 @@ func New(cfg *config.Config) (*Server, error) {
|
||||
|
||||
return srv, nil
|
||||
}
|
||||
|
||||
func (srv *Server) SelectLease(req *dhcp.BootRequest, t time.Time) *iptools.LeaseInfo {
|
||||
if li, ok := srv.Static[req.HostName]; ok {
|
||||
return li
|
||||
}
|
||||
|
||||
if pool, ok := srv.Pools[req.HostName]; ok {
|
||||
return pool.Peek(t, MaxResponseWait)
|
||||
}
|
||||
|
||||
if pool, ok := srv.Pools[DefaultPool]; ok {
|
||||
return pool.Peek(t, MaxResponseWait)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user