chore: Refactor package structure

This commit is contained in:
Adrian Rumpold
2024-01-04 18:49:54 +01:00
parent 13677eaf54
commit 001517eb15
5 changed files with 89 additions and 79 deletions

80
main.go
View File

@@ -6,43 +6,31 @@ import (
"net" "net"
"unsafe" "unsafe"
"github.com/adrianokf/go-dhcp/pkg/leases"
"github.com/adrianokf/go-dhcp/pkg/messages"
"github.com/adrianokf/go-dhcp/pkg/types"
"go.uber.org/zap" "go.uber.org/zap"
) )
var manager = NewLeaseManager() var manager = leases.NewLeaseManager()
var leases []Lease = make([]Lease, 0) var magic = [4]byte{0x63, 0x82, 0x53, 0x63}
func (dhcp DhcpMessage) Debug(s *zap.SugaredLogger) { func parseOptions(data []byte) messages.Options {
s.Debugf("op=%x, htype=%x, hlen=%x, hops=%x", dhcp.Op, dhcp.Htype, dhcp.Hlen, dhcp.Hops)
s.Debugf("xid=%x", dhcp.Xid)
s.Debugf("secs=%d, flags=%x", dhcp.Secs, dhcp.Flags)
s.Debugf("ciaddr=%x", dhcp.Ciaddr)
s.Debugf("siaddr=%x", dhcp.Siaddr)
s.Debugf("giaddr=%x", dhcp.Giaddr)
s.Debugf("chaddr=%x", dhcp.Chaddr)
s.Debugf("sname=%s", string(dhcp.Sname[:]))
s.Debugf("file=%s", string(dhcp.File[:]))
s.Debugf("magic=%x", dhcp.Magic)
}
func parseOptions(data []byte) Options {
s := zap.S() s := zap.S()
i := 0 i := 0
options := make(Options) options := make(messages.Options)
out: out:
for i < len(data) { for i < len(data) {
code := OptionCode(data[i]) code := messages.OptionCode(data[i])
switch code { switch code {
case OptionEnd: case messages.OptionEnd:
s.Debug("Found END option at offset ", i) s.Debug("Found END option at offset ", i)
break out break out
case OptionPad: case messages.OptionPad:
s.Debug("Found padding option at offset ", i) s.Debug("Found padding option at offset ", i)
i += 1 i += 1
continue continue
@@ -52,7 +40,7 @@ out:
payload := data[i+2 : i+2+size] payload := data[i+2 : i+2+size]
s.Debugf("code=%d, size=%d, payload=%x", code, size, payload) s.Debugf("code=%d, size=%d, payload=%x", code, size, payload)
options[code] = Option{Code: code, Data: data[i+1 : i+2+size]} options[code] = messages.Option{Code: code, Data: data[i+1 : i+2+size]}
i += size + 2 i += size + 2
} }
@@ -60,15 +48,15 @@ out:
return options return options
} }
func prepareOffer(request DhcpMessage, lease Lease) DhcpMessage { func prepareOffer(request messages.DhcpMessage, lease leases.Lease) messages.DhcpMessage {
var sname [64]byte var sname [64]byte
var file [128]byte var file [128]byte
var siaddr Ipv4Addr var siaddr types.Ipv4Addr
copy(sname[:], "go-dhcp-server") copy(sname[:], "go-dhcp-server")
copy(siaddr[:], net.IPv4(10, 0, 0, 1).To4()) copy(siaddr[:], net.IPv4(10, 0, 0, 1).To4())
dhcp := DhcpMessage{ dhcp := messages.DhcpMessage{
Op: BOOTREPLY, Op: messages.BOOTREPLY,
Htype: 1, // Ethernet Htype: 1, // Ethernet
Hlen: 6, // Ethernet address length Hlen: 6, // Ethernet address length
Hops: 0, Hops: 0,
@@ -87,13 +75,13 @@ func prepareOffer(request DhcpMessage, lease Lease) DhcpMessage {
return dhcp return dhcp
} }
func prepareAck(request DhcpMessage, lease Lease) DhcpMessage { func prepareAck(request messages.DhcpMessage, lease leases.Lease) messages.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")
dhcp := DhcpMessage{ dhcp := messages.DhcpMessage{
Op: BOOTREPLY, Op: messages.BOOTREPLY,
Htype: 1, // Ethernet Htype: 1, // Ethernet
Hlen: 6, // Ethernet address length Hlen: 6, // Ethernet address length
Hops: 0, Hops: 0,
@@ -115,7 +103,7 @@ func prepareAck(request DhcpMessage, lease Lease) DhcpMessage {
// sendMessage transmits a DHCP message with options via a UDP connection // sendMessage transmits a DHCP message with options via a UDP connection
// The end option (code 255) is automatically appended and does not need to // The end option (code 255) is automatically appended and does not need to
// be passed explicitly. // be passed explicitly.
func sendMessage(conn *net.UDPConn, message DhcpMessage, options []Option) error { func sendMessage(conn *net.UDPConn, message messages.DhcpMessage, options []messages.Option) error {
buf := make([]byte, 0) buf := make([]byte, 0)
w := bytes.NewBuffer(buf) w := bytes.NewBuffer(buf)
err := binary.Write(w, binary.BigEndian, message) err := binary.Write(w, binary.BigEndian, message)
@@ -136,7 +124,7 @@ func sendMessage(conn *net.UDPConn, message DhcpMessage, options []Option) error
// Automatically add END option, so the caller doesn't // Automatically add END option, so the caller doesn't
// need to specificy it for every invocation. // need to specificy it for every invocation.
err = w.WriteByte(byte(OptionEnd)) err = w.WriteByte(byte(messages.OptionEnd))
if err != nil { if err != nil {
return err return err
} }
@@ -151,7 +139,7 @@ func sendMessage(conn *net.UDPConn, message DhcpMessage, options []Option) error
return nil return nil
} }
func handleOffer(dhcp DhcpMessage, remote *net.UDPAddr) error { func handleOffer(dhcp messages.DhcpMessage, remote *net.UDPAddr) error {
s := zap.S() s := zap.S()
lease, err := manager.Request(dhcp.Xid, dhcp.Chaddr) lease, err := manager.Request(dhcp.Xid, dhcp.Chaddr)
@@ -168,17 +156,17 @@ func handleOffer(dhcp DhcpMessage, remote *net.UDPAddr) error {
defer conn.Close() defer conn.Close()
s.Info("Sending DHCPOFFER...") s.Info("Sending DHCPOFFER...")
options := []Option{ options := []messages.Option{
{ {
Code: OptionDHCPMessageType, Code: messages.OptionDHCPMessageType,
Data: []byte{1, byte(MessageTypeOffer)}, Data: []byte{1, byte(messages.MessageTypeOffer)},
}, },
} }
sendMessage(conn, offer, options) sendMessage(conn, offer, options)
return nil return nil
} }
func handleAck(dhcp DhcpMessage, remote *net.UDPAddr) error { func handleAck(dhcp messages.DhcpMessage, remote *net.UDPAddr) error {
s := zap.S() s := zap.S()
lease, err := manager.Lookup(dhcp.Xid) lease, err := manager.Lookup(dhcp.Xid)
@@ -188,13 +176,13 @@ func handleAck(dhcp DhcpMessage, remote *net.UDPAddr) error {
ack := prepareAck(dhcp, *lease) ack := prepareAck(dhcp, *lease)
options := []Option{ options := []messages.Option{
{ {
Code: OptionDHCPMessageType, Code: messages.OptionDHCPMessageType,
Data: []byte{1, byte(MessageTypeAck)}, Data: []byte{1, byte(messages.MessageTypeAck)},
}, },
{ {
Code: OptionIPAddressLeaseTime, Code: messages.OptionIPAddressLeaseTime,
Data: append([]byte{4}, u32tob(3600)...), Data: append([]byte{4}, u32tob(3600)...),
}, },
} }
@@ -224,7 +212,7 @@ func handleMsg(data []byte, remote *net.UDPAddr) {
s.Debugf("Connection from client %v", remote.IP) s.Debugf("Connection from client %v", remote.IP)
var dhcp DhcpMessage var dhcp messages.DhcpMessage
reader := bytes.NewReader(data) reader := bytes.NewReader(data)
binary.Read(reader, binary.BigEndian, &dhcp) binary.Read(reader, binary.BigEndian, &dhcp)
dhcp.Debug(s) dhcp.Debug(s)
@@ -238,14 +226,14 @@ func handleMsg(data []byte, remote *net.UDPAddr) {
s.Debug("Raw options data:", optData) s.Debug("Raw options data:", optData)
options := parseOptions(optData) options := parseOptions(optData)
dhcpMsgType := options[OptionDHCPMessageType] dhcpMsgType := options[messages.OptionDHCPMessageType]
s.Info("DHCP message type ", dhcpMsgType) s.Info("DHCP message type ", dhcpMsgType)
switch MessageType(dhcpMsgType.Data[1]) { switch messages.MessageType(dhcpMsgType.Data[1]) {
case MessageTypeDiscover: case messages.MessageTypeDiscover:
go handleOffer(dhcp, remote) go handleOffer(dhcp, remote)
case MessageTypeRequest: case messages.MessageTypeRequest:
go handleAck(dhcp, remote) go handleAck(dhcp, remote)
} }
} }

View File

@@ -1,32 +1,48 @@
package main package leases
import ( import (
"errors" "errors"
"fmt" "fmt"
"time" "time"
"github.com/adrianokf/go-dhcp/pkg/types"
"go.uber.org/zap" "go.uber.org/zap"
) )
type LeaseState uint8
const (
Offered LeaseState = iota
Requested
)
type Lease struct {
TransactionId types.TxId
TTL time.Time
State LeaseState
ClientAddr types.HwAddr
Address types.Ipv4Addr
}
type ILeaseManager interface { type ILeaseManager interface {
Request(xid TxId, clientAddr HwAddr) (*Lease, error) Request(xid types.TxId, clientAddr types.HwAddr) (*Lease, error)
Release(l Lease) error Release(l Lease) error
Lookup(xid TxId) error Lookup(xid types.TxId) error
} }
type LeaseManager struct { type LeaseManager struct {
leases map[TxId]Lease leases map[types.TxId]Lease
count byte count byte
} }
func NewLeaseManager() *LeaseManager { func NewLeaseManager() *LeaseManager {
m := &LeaseManager{ m := &LeaseManager{
leases: make(map[TxId]Lease), leases: make(map[types.TxId]Lease),
} }
return m return m
} }
func (m *LeaseManager) Request(xid TxId, clientAddr HwAddr) (*Lease, error) { func (m *LeaseManager) Request(xid types.TxId, clientAddr types.HwAddr) (*Lease, error) {
zap.S().Debugf("LeaseManager.Request(%v, %v)", xid, clientAddr) zap.S().Debugf("LeaseManager.Request(%v, %v)", xid, clientAddr)
if m.count > 254 { if m.count > 254 {
@@ -58,7 +74,7 @@ func (m LeaseManager) Release(l Lease) error {
return nil return nil
} }
func (m LeaseManager) Lookup(xid TxId) (*Lease, error) { func (m LeaseManager) Lookup(xid types.TxId) (*Lease, error) {
lease, found := m.leases[xid] lease, found := m.leases[xid]
if found { if found {
return &lease, nil return &lease, nil

View File

@@ -1,9 +1,15 @@
package main package messages
import ( import (
"time" "github.com/adrianokf/go-dhcp/pkg/types"
"go.uber.org/zap"
) )
type Message interface {
Marshal() ([]byte, error)
Unmarshal([]byte) (Message, error)
}
type OptionCode byte type OptionCode byte
// DHCPv4 Options // DHCPv4 Options
@@ -195,40 +201,35 @@ const (
MessageTypeInform MessageTypeInform
) )
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 TxId Xid types.TxId
Secs uint16 Secs uint16
Flags uint16 Flags uint16
Ciaddr Ipv4Addr Ciaddr types.Ipv4Addr
Yiaddr Ipv4Addr Yiaddr types.Ipv4Addr
Siaddr Ipv4Addr Siaddr types.Ipv4Addr
Giaddr Ipv4Addr Giaddr types.Ipv4Addr
Chaddr HwAddr Chaddr types.HwAddr
Sname [64]byte Sname [64]byte
File [128]byte File [128]byte
Magic [4]byte Magic [4]byte
} }
const ( func (dhcp DhcpMessage) Debug(s *zap.SugaredLogger) {
Offered LeaseState = iota s.Debugf("op=%x, htype=%x, hlen=%x, hops=%x", dhcp.Op, dhcp.Htype, dhcp.Hlen, dhcp.Hops)
Requested s.Debugf("xid=%x", dhcp.Xid)
) s.Debugf("secs=%d, flags=%x", dhcp.Secs, dhcp.Flags)
type Lease struct { s.Debugf("ciaddr=%x", dhcp.Ciaddr)
TransactionId TxId s.Debugf("siaddr=%x", dhcp.Siaddr)
TTL time.Time s.Debugf("giaddr=%x", dhcp.Giaddr)
State LeaseState s.Debugf("chaddr=%x", dhcp.Chaddr)
ClientAddr HwAddr
Address Ipv4Addr s.Debugf("sname=%s", string(dhcp.Sname[:]))
s.Debugf("file=%s", string(dhcp.File[:]))
s.Debugf("magic=%x", dhcp.Magic)
} }

View File

@@ -1,4 +1,4 @@
package main package messages
type Option struct { type Option struct {
Code OptionCode Code OptionCode

5
pkg/types/types.go Normal file
View File

@@ -0,0 +1,5 @@
package types
type TxId [4]byte
type Ipv4Addr [4]byte
type HwAddr [16]byte