dnsmasq-netbox-connector/internal/dnsmasq/dnsmasq.go

83 lines
1.9 KiB
Go

package dnsmasq
import (
"fmt"
"net/netip"
"os"
"strconv"
"strings"
"time"
)
type Lease struct {
ExpireDate time.Time
Mac string
IP netip.Addr
Hostname string
ClientID string
}
func (l Lease) String() string {
return fmt.Sprintf("[expire on %v]: host %s IP %s (mac %s - clientID %s)", l.ExpireDate, l.Hostname, l.IP, l.Mac, l.ClientID)
}
func parseLeaseLine(rawLine string) (*Lease, error) {
lineValues := strings.Split(rawLine, " ")
if len(lineValues) != 5 {
return nil, fmt.Errorf("unexpected number of values, expected 5, got %d", len(lineValues))
}
expireTimeInt, err := strconv.Atoi(lineValues[0])
if err != nil {
return nil, fmt.Errorf("unexpected unix timestamp value %s", lineValues[0])
}
ip, err := netip.ParseAddr(lineValues[2])
if err != nil {
return nil, fmt.Errorf("unexpected IP address: %s: %w", lineValues[2], err)
}
return &Lease{
ExpireDate: time.Unix(int64(expireTimeInt), 0),
Mac: lineValues[1],
IP: ip,
Hostname: lineValues[3],
ClientID: lineValues[4],
}, nil
}
func GetLeases(leasesPath string) ([]*Lease, error) {
fileContent, err := os.ReadFile(leasesPath)
if err != nil {
return nil, fmt.Errorf("failed to read leases file: %w", err)
}
leases := []*Lease{}
for i, l := range strings.Split(string(fileContent), "\n") {
if l == "" {
continue
}
lease, err := parseLeaseLine(l)
if err != nil {
return nil, fmt.Errorf("failed to parse line %d: %w", i, err)
}
leases = append(leases, lease)
}
return leases, nil
}
func GetDynamicLeases(leasesPath string, dhcpStart, dhcpEnd netip.Addr) ([]*Lease, error) {
allLeases, err := GetLeases(leasesPath)
if err != nil {
return nil, err
}
filteredLeases := []*Lease{}
for _, l := range allLeases {
if l.IP.Less(dhcpEnd) && dhcpStart.Less(l.IP) {
filteredLeases = append(filteredLeases, l)
}
}
return filteredLeases, nil
}