fix: Fix connection interface binding, JSON lease DB
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
package leases
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/adrianokf/go-dhcp/pkg/types"
|
||||
@@ -16,12 +19,14 @@ const (
|
||||
Requested
|
||||
)
|
||||
|
||||
const DumpFile = "/var/lib/go-dhcp/leases.json"
|
||||
|
||||
type Lease struct {
|
||||
TransactionId types.TxId
|
||||
TTL time.Time
|
||||
State LeaseState
|
||||
ClientAddr types.HwAddr
|
||||
Address types.Ipv4Addr
|
||||
TransactionId types.TxId `json:"TransactionID"`
|
||||
TTL time.Time `json:"TTL"`
|
||||
State LeaseState `json:"State"`
|
||||
ClientAddr types.HwAddr `json:"ClientAddr"`
|
||||
Address types.Ipv4Addr `json:"Address"`
|
||||
}
|
||||
|
||||
type ILeaseManager interface {
|
||||
@@ -35,9 +40,51 @@ type LeaseManager struct {
|
||||
count byte
|
||||
}
|
||||
|
||||
func (m LeaseManager) DumpLeases() {
|
||||
err := os.MkdirAll(filepath.Dir(DumpFile), 0755)
|
||||
if err != nil {
|
||||
zap.S().Panic(err)
|
||||
}
|
||||
|
||||
f, err := os.Create(DumpFile)
|
||||
if err != nil {
|
||||
zap.S().Panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
leases := make([]Lease, len(m.leases))
|
||||
for _, l := range m.leases {
|
||||
leases = append(leases, l)
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(f)
|
||||
enc.Encode(leases)
|
||||
f.Sync()
|
||||
}
|
||||
|
||||
func LoadLeases() (map[types.TxId]Lease, error) {
|
||||
var leaseMap = make(map[types.TxId]Lease)
|
||||
|
||||
data, err := os.ReadFile(DumpFile)
|
||||
if err != nil {
|
||||
return leaseMap, err
|
||||
}
|
||||
var leases []Lease
|
||||
json.Unmarshal(data, &leases)
|
||||
|
||||
for _, l := range leases {
|
||||
leaseMap[l.TransactionId] = l
|
||||
}
|
||||
return leaseMap, nil
|
||||
}
|
||||
|
||||
func NewLeaseManager() *LeaseManager {
|
||||
leases, err := LoadLeases()
|
||||
if err != nil {
|
||||
zap.S().Warnf("Could not restore saved leases from %s: %s", DumpFile, err)
|
||||
}
|
||||
m := &LeaseManager{
|
||||
leases: make(map[types.TxId]Lease),
|
||||
leases: leases,
|
||||
}
|
||||
return m
|
||||
}
|
||||
@@ -62,6 +109,9 @@ func (m *LeaseManager) Request(xid types.TxId, clientAddr types.HwAddr) (*Lease,
|
||||
m.count += 1
|
||||
|
||||
zap.S().Debug("lease=", lease)
|
||||
|
||||
m.DumpLeases()
|
||||
|
||||
return &lease, nil
|
||||
}
|
||||
|
||||
@@ -71,6 +121,9 @@ func (m LeaseManager) Release(l Lease) error {
|
||||
return fmt.Errorf("invalid lease %v", l)
|
||||
}
|
||||
delete(m.leases, l.TransactionId)
|
||||
|
||||
m.DumpLeases()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
46
pkg/types/json.go
Normal file
46
pkg/types/json.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
util "github.com/adrianokf/go-dhcp/pkg/util"
|
||||
)
|
||||
|
||||
func (txid *TxId) UnmarshalText(text []byte) (err error) {
|
||||
result, err := strconv.ParseUint(string(text), 16, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
copy(txid[:], util.U32ToByte(uint32(result)))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (id TxId) MarshalText() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("%x", id)), nil
|
||||
}
|
||||
|
||||
func (addr *Ipv4Addr) UnmarshalText(text []byte) (err error) {
|
||||
ip := net.ParseIP(string(text))
|
||||
fmt.Println(ip)
|
||||
if ip == nil {
|
||||
return fmt.Errorf("could not parse IP address: '%s'", text)
|
||||
}
|
||||
*addr = Ipv4AddrFromNetIP(ip)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (addr Ipv4Addr) MarshalText() ([]byte, error) {
|
||||
return addr.ToNetIPv4().MarshalText()
|
||||
}
|
||||
|
||||
func (addr HwAddr) MarshalText() ([]byte, error) {
|
||||
return []byte(addr.String()), nil
|
||||
}
|
||||
|
||||
func (addr *HwAddr) UnmarshalText(text []byte) (err error) {
|
||||
*addr, err = HwAddrFromString(string(text))
|
||||
return err
|
||||
}
|
||||
@@ -1,5 +1,37 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
type TxId [4]byte
|
||||
type Ipv4Addr [4]byte
|
||||
type HwAddr [16]byte
|
||||
|
||||
const (
|
||||
ServerPort = 67
|
||||
ClientPort = 68
|
||||
)
|
||||
|
||||
func Ipv4AddrFromNetIP(ip net.IP) Ipv4Addr {
|
||||
ipv4 := ip.To4()
|
||||
return Ipv4Addr{ipv4[0], ipv4[1], ipv4[2], ipv4[3]}
|
||||
}
|
||||
|
||||
func (addr Ipv4Addr) ToNetIPv4() net.IP {
|
||||
return net.IPv4(addr[0], addr[1], addr[2], addr[3])
|
||||
}
|
||||
|
||||
func (addr Ipv4Addr) String() string {
|
||||
return addr.ToNetIPv4().String()
|
||||
}
|
||||
|
||||
func (addr HwAddr) String() string {
|
||||
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
|
||||
}
|
||||
|
||||
func HwAddrFromString(s string) (addr HwAddr, err error) {
|
||||
_, err = fmt.Sscanf(s, "%02x:%02x:%02x:%02x:%02x:%02x", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5])
|
||||
return addr, err
|
||||
}
|
||||
|
||||
11
pkg/util/util.go
Normal file
11
pkg/util/util.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
func U32ToByte(u uint32) []byte {
|
||||
buf := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(buf, u)
|
||||
return buf
|
||||
}
|
||||
Reference in New Issue
Block a user