mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
internal/clientinfo: add kea-dhcp4 parser
This commit is contained in:
committed by
Cuong Manh Le
parent
eaad24e5e5
commit
9c1665a759
@@ -18,4 +18,5 @@ type LeaseFileFormat string
|
||||
const (
|
||||
Dnsmasq LeaseFileFormat = "dnsmasq"
|
||||
IscDhcpd LeaseFileFormat = "isc-dhcpd"
|
||||
KeaDHCP4 LeaseFileFormat = "kea-dhcp4"
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ package clientinfo
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -202,7 +203,8 @@ func (d *dhcp) dnsmasqReadClientInfoFile(name string) error {
|
||||
|
||||
}
|
||||
|
||||
// dnsmasqReadClientInfoReader likes ctrld.Dnsmasq, but reading from an io.Reader instead of file.
|
||||
// dnsmasqReadClientInfoReader performs the same task as dnsmasqReadClientInfoFile,
|
||||
// but by reading from an io.Reader instead of file.
|
||||
func (d *dhcp) dnsmasqReadClientInfoReader(reader io.Reader) error {
|
||||
return lineread.Reader(reader, func(line []byte) error {
|
||||
fields := bytes.Fields(line)
|
||||
@@ -244,7 +246,8 @@ func (d *dhcp) iscDHCPReadClientInfoFile(name string) error {
|
||||
return d.iscDHCPReadClientInfoReader(f)
|
||||
}
|
||||
|
||||
// iscDHCPReadClientInfoReader likes ctrld.IscDhcpd, but reading from an io.Reader instead of file.
|
||||
// iscDHCPReadClientInfoReader performs the same task as iscDHCPReadClientInfoFile,
|
||||
// but by reading from an io.Reader instead of file.
|
||||
func (d *dhcp) iscDHCPReadClientInfoReader(reader io.Reader) error {
|
||||
s := bufio.NewScanner(reader)
|
||||
var ip, mac, hostname string
|
||||
@@ -287,6 +290,58 @@ func (d *dhcp) iscDHCPReadClientInfoReader(reader io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// keaDhcp4ReadClientInfoFile populates dhcp table with client info reading from kea dhcp4 lease file.
|
||||
func (d *dhcp) keaDhcp4ReadClientInfoFile(name string) error {
|
||||
f, err := os.Open(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
return d.keaDhcp4ReadClientInfoReader(bufio.NewReader(f))
|
||||
|
||||
}
|
||||
|
||||
// keaDhcp4ReadClientInfoReader performs the same task as keaDhcp4ReadClientInfoFile,
|
||||
// but by reading from an io.Reader instead of file.
|
||||
func (d *dhcp) keaDhcp4ReadClientInfoReader(r io.Reader) error {
|
||||
cr := csv.NewReader(r)
|
||||
for {
|
||||
record, err := cr.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(record) < 9 {
|
||||
continue // hostname is at 9th field, so skipping record with not enough fields.
|
||||
}
|
||||
if record[0] == "address" {
|
||||
continue // skip header.
|
||||
}
|
||||
mac := record[1]
|
||||
if _, err := net.ParseMAC(mac); err != nil { // skip invalid MAC
|
||||
continue
|
||||
}
|
||||
ip := normalizeIP(record[0])
|
||||
if net.ParseIP(ip) == nil {
|
||||
ctrld.ProxyLogger.Load().Warn().Msgf("invalid ip address entry: %q", ip)
|
||||
ip = ""
|
||||
}
|
||||
|
||||
d.mac.Store(ip, mac)
|
||||
d.ip.Store(mac, ip)
|
||||
hostname := record[8]
|
||||
if hostname == "*" {
|
||||
continue
|
||||
}
|
||||
name := normalizeHostname(hostname)
|
||||
d.mac2name.Store(mac, name)
|
||||
d.ip2name.Store(ip, name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// addSelf populates current host info to dhcp, so queries from
|
||||
// the host itself can be attached with proper client info.
|
||||
func (d *dhcp) addSelf() {
|
||||
|
||||
@@ -15,4 +15,5 @@ var clientInfoFiles = map[string]ctrld.LeaseFileFormat{
|
||||
"/run/dhcpd.leases": ctrld.IscDhcpd, // EdgeOS
|
||||
"/var/dhcpd/var/db/dhcpd.leases": ctrld.IscDhcpd, // Pfsense
|
||||
"/home/pi/.router/run/dhcp/dnsmasq.leases": ctrld.Dnsmasq, // Firewalla
|
||||
"/var/lib/kea/dhcp4.leases": ctrld.KeaDHCP4, // Pfsense
|
||||
}
|
||||
|
||||
@@ -67,6 +67,41 @@ lease 192.168.1.2 {
|
||||
"00:00:00:00:00:04",
|
||||
"example",
|
||||
},
|
||||
{
|
||||
"kea-dhcp4 good",
|
||||
`address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context,pool_id
|
||||
192.168.0.123,00:00:00:00:00:05,00:00:00:00:00:05,7200,1703290639,1,0,0,foo,0,,0
|
||||
`,
|
||||
d.keaDhcp4ReadClientInfoReader,
|
||||
"00:00:00:00:00:05",
|
||||
"foo",
|
||||
},
|
||||
{
|
||||
"kea-dhcp4 no-header",
|
||||
`192.168.0.123,00:00:00:00:00:05,00:00:00:00:00:05,7200,1703290639,1,0,0,foo,0,,0`,
|
||||
d.keaDhcp4ReadClientInfoReader,
|
||||
"00:00:00:00:00:05",
|
||||
"foo",
|
||||
},
|
||||
{
|
||||
"kea-dhcp4 hostname *",
|
||||
`address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context,pool_id
|
||||
192.168.0.123,00:00:00:00:00:05,00:00:00:00:00:05,7200,1703290639,1,0,0,*,0,,0
|
||||
`,
|
||||
d.keaDhcp4ReadClientInfoReader,
|
||||
"00:00:00:00:00:05",
|
||||
"*",
|
||||
},
|
||||
{
|
||||
"kea-dhcp4 bad",
|
||||
`address,hwaddr,client_id,valid_lifetime,expire,subnet_id,fqdn_fwd,fqdn_rev,hostname,state,user_context,pool_id
|
||||
192.168.0.123,00:00:00:00:00:05,00:00:00:00:00:05,7200,1703290639,1,0,0,foo,0,,0
|
||||
192.168.0.124,invalid_MAC,00:00:00:00:00:05,7200,1703290639,1,0,0,foo,0,,0
|
||||
`,
|
||||
d.keaDhcp4ReadClientInfoReader,
|
||||
"00:00:00:00:00:05",
|
||||
"foo",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
@@ -76,6 +111,12 @@ lease 192.168.1.2 {
|
||||
t.Errorf("readClientInfoReader() error = %v", err)
|
||||
}
|
||||
val, existed := d.mac2name.Load(tc.mac)
|
||||
if tc.hostname == "*" {
|
||||
if existed {
|
||||
t.Errorf("* hostname must be skipped")
|
||||
}
|
||||
return
|
||||
}
|
||||
if !existed {
|
||||
t.Error("client info missing")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user