feat: Working lease manager

This commit is contained in:
Adrian Rumpold
2022-02-20 12:47:29 +01:00
parent 9f83d6f3f5
commit 234582e586
3 changed files with 110 additions and 31 deletions

67
lease.go Normal file
View File

@@ -0,0 +1,67 @@
package main
import (
"errors"
"fmt"
"time"
"go.uber.org/zap"
)
type ILeaseManager interface {
Request(xid TxId, clientAddr HwAddr) (*Lease, error)
Release(l Lease) error
Lookup(xid TxId) error
}
type LeaseManager struct {
leases map[TxId]Lease
count byte
}
func NewLeaseManager() *LeaseManager {
m := &LeaseManager{
leases: make(map[TxId]Lease),
}
return m
}
func (m *LeaseManager) Request(xid TxId, clientAddr HwAddr) (*Lease, error) {
zap.S().Debugf("LeaseManager.Request(%v, %v)", xid, clientAddr)
if m.count > 254 {
return nil, errors.New("lease address pool exhausted")
}
assigned := [4]byte{10, 0, 0, m.count + 2}
lease := Lease{
TransactionId: xid,
TTL: time.Now().Add(1 * time.Hour),
State: Requested,
ClientAddr: clientAddr,
Address: assigned,
}
m.leases[xid] = lease
m.count += 1
zap.S().Debug("lease=", lease)
return &lease, nil
}
func (m LeaseManager) Release(l Lease) error {
_, found := m.leases[l.TransactionId]
if !found {
return fmt.Errorf("invalid lease %v", l)
}
delete(m.leases, l.TransactionId)
return nil
}
func (m LeaseManager) Lookup(xid TxId) (*Lease, error) {
lease, found := m.leases[xid]
if found {
return &lease, nil
}
return nil, fmt.Errorf("no lease found for xid %v", xid)
}

50
main.go
View File

@@ -4,12 +4,13 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"net" "net"
"time"
"unsafe" "unsafe"
"go.uber.org/zap" "go.uber.org/zap"
) )
var manager = NewLeaseManager()
var leases []Lease = make([]Lease, 0) var leases []Lease = make([]Lease, 0)
func (dhcp DhcpMessage) Debug(s *zap.SugaredLogger) { func (dhcp DhcpMessage) Debug(s *zap.SugaredLogger) {
@@ -59,10 +60,12 @@ out:
return options return options
} }
func prepareOffer(request DhcpMessage) DhcpMessage { func prepareOffer(request DhcpMessage, lease Lease) DhcpMessage {
var sname [64]byte var sname [64]byte
var file [128]byte var file [128]byte
var siaddr Ipv4Addr
copy(sname[:], "go-dhcp-server") copy(sname[:], "go-dhcp-server")
copy(siaddr[:], net.IPv4(10, 0, 0, 1).To4())
dhcp := DhcpMessage{ dhcp := DhcpMessage{
Op: BOOTREPLY, Op: BOOTREPLY,
@@ -71,20 +74,20 @@ func prepareOffer(request DhcpMessage) DhcpMessage {
Hops: 0, Hops: 0,
Secs: 0, Secs: 0,
Flags: request.Flags, Flags: request.Flags,
Xid: request.Xid, Xid: lease.TransactionId,
Siaddr: binary.BigEndian.Uint32(net.IPv4(10, 0, 0, 1).To4()), Siaddr: siaddr,
Ciaddr: 0, Ciaddr: [4]byte{0, 0, 0, 0},
Yiaddr: binary.BigEndian.Uint32(net.IPv4(10, 0, 0, 2).To4()), Yiaddr: lease.Address,
Giaddr: request.Giaddr, Giaddr: request.Giaddr,
Chaddr: request.Chaddr, Chaddr: request.Chaddr,
Magic: [4]byte{0x63, 0x82, 0x53, 0x63}, Magic: magic,
Sname: sname, Sname: sname,
File: file, File: file,
} }
return dhcp return dhcp
} }
func prepareAck(request DhcpMessage) DhcpMessage { func prepareAck(request DhcpMessage, lease Lease) DhcpMessage {
var sname [64]byte var sname [64]byte
var file [128]byte var file [128]byte
copy(sname[:], "go-dhcp-server") copy(sname[:], "go-dhcp-server")
@@ -97,12 +100,12 @@ func prepareAck(request DhcpMessage) DhcpMessage {
Secs: 0, Secs: 0,
Flags: 0, Flags: 0,
Xid: request.Xid, Xid: request.Xid,
Siaddr: binary.BigEndian.Uint32(net.IPv4(10, 0, 0, 1).To4()), Siaddr: lease.Address,
Ciaddr: request.Ciaddr, Ciaddr: request.Ciaddr,
Yiaddr: binary.BigEndian.Uint32(net.IPv4(10, 0, 0, 2).To4()), Yiaddr: lease.Address,
Giaddr: request.Giaddr, Giaddr: request.Giaddr,
Chaddr: request.Chaddr, Chaddr: request.Chaddr,
Magic: [4]byte{0x63, 0x82, 0x53, 0x63}, Magic: magic,
Sname: sname, Sname: sname,
File: file, File: file,
} }
@@ -151,7 +154,11 @@ func sendMessage(conn *net.UDPConn, message DhcpMessage, options []Option) error
func handleOffer(dhcp DhcpMessage, remote *net.UDPAddr) error { func handleOffer(dhcp DhcpMessage, remote *net.UDPAddr) error {
s := zap.S() s := zap.S()
offer := prepareOffer(dhcp) lease, err := manager.Request(dhcp.Xid, dhcp.Chaddr)
if err != nil {
panic(err)
}
offer := prepareOffer(dhcp, *lease)
localAddr, _ := net.ResolveUDPAddr("udp", "172.17.0.1:68") localAddr, _ := net.ResolveUDPAddr("udp", "172.17.0.1:68")
clientAddr, _ := net.ResolveUDPAddr("udp", "255.255.255.255:68") clientAddr, _ := net.ResolveUDPAddr("udp", "255.255.255.255:68")
conn, err := net.DialUDP("udp", localAddr, clientAddr) conn, err := net.DialUDP("udp", localAddr, clientAddr)
@@ -174,7 +181,12 @@ func handleOffer(dhcp DhcpMessage, remote *net.UDPAddr) error {
func handleAck(dhcp DhcpMessage, remote *net.UDPAddr) error { func handleAck(dhcp DhcpMessage, remote *net.UDPAddr) error {
s := zap.S() s := zap.S()
ack := prepareAck(dhcp) lease, err := manager.Lookup(dhcp.Xid)
if err != nil {
panic(err)
}
ack := prepareAck(dhcp, *lease)
options := []Option{ options := []Option{
{ {
@@ -199,15 +211,11 @@ func handleAck(dhcp DhcpMessage, remote *net.UDPAddr) error {
s.Info("Sending DHCPACK") s.Info("Sending DHCPACK")
sendMessage(conn, ack, options) sendMessage(conn, ack, options)
lease := Lease{ lease, err = manager.Request(dhcp.Xid, dhcp.Chaddr)
TransactionId: ack.Xid, if err != nil {
TTL: time.Now().Add(1 * time.Hour), return err
State: Requested,
ClientAddr: ack.Chaddr,
Address: int2ip(ack.Yiaddr),
} }
leases = append(leases, lease) s.Debug("Found lease", lease)
return nil return nil
} }

View File

@@ -1,7 +1,6 @@
package main package main
import ( import (
"net"
"time" "time"
) )
@@ -197,20 +196,25 @@ const (
) )
type LeaseState uint8 type LeaseState uint8
type TxId [4]byte
type Ipv4Addr [4]byte
type HwAddr [16]byte
var magic = [4]byte{0x63, 0x82, 0x53, 0x63}
type DhcpMessage struct { type DhcpMessage struct {
Op DhcpOp Op DhcpOp
Htype MessageType Htype MessageType
Hlen byte Hlen byte
Hops byte Hops byte
Xid uint32 Xid TxId
Secs uint16 Secs uint16
Flags uint16 Flags uint16
Ciaddr uint32 Ciaddr Ipv4Addr
Yiaddr uint32 Yiaddr Ipv4Addr
Siaddr uint32 Siaddr Ipv4Addr
Giaddr uint32 Giaddr Ipv4Addr
Chaddr [16]byte Chaddr HwAddr
Sname [64]byte Sname [64]byte
File [128]byte File [128]byte
Magic [4]byte Magic [4]byte
@@ -222,9 +226,9 @@ const (
) )
type Lease struct { type Lease struct {
TransactionId uint32 TransactionId TxId
TTL time.Time TTL time.Time
State LeaseState State LeaseState
ClientAddr [16]byte ClientAddr HwAddr
Address net.IP Address Ipv4Addr
} }