diff options
Diffstat (limited to '')
-rw-r--r-- | src/go/collectors/go.d.plugin/modules/isc_dhcpd/parse.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/isc_dhcpd/parse.go b/src/go/collectors/go.d.plugin/modules/isc_dhcpd/parse.go new file mode 100644 index 000000000..cb4161745 --- /dev/null +++ b/src/go/collectors/go.d.plugin/modules/isc_dhcpd/parse.go @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package isc_dhcpd + +import ( + "bufio" + "bytes" + "net" + "os" +) + +/* +Documentation (v4.4): https://kb.isc.org/docs/en/isc-dhcp-44-manual-pages-dhcpdleases + +DHCPv4 prepare declaration: + prepare ip-address { + statements... + } + +DHCPv6 prepare declaration: + ia_ta IAID_DUID { + cltt date; + iaaddr ipv6-address { + statements... + } + } + ia_na IAID_DUID { + cltt date; + iaaddr ipv6-address { + statements... + } + } + ia_pd IAID_DUID { + cltt date; + iaprefix ipv6-address/prefix-length { + statements... + } + } +*/ + +type leaseEntry struct { + ip net.IP + bindingState string +} + +func (l leaseEntry) hasIP() bool { return l.ip != nil } +func (l leaseEntry) hasBindingState() bool { return l.bindingState != "" } + +func parseDHCPdLeasesFile(filepath string) ([]leaseEntry, error) { + f, err := os.Open(filepath) + if err != nil { + return nil, err + } + defer func() { _ = f.Close() }() + + leasesSet := make(map[string]leaseEntry) + l := leaseEntry{} + sc := bufio.NewScanner(f) + + for sc.Scan() { + bs := bytes.TrimSpace(sc.Bytes()) + switch { + case !l.hasIP() && bytes.HasPrefix(bs, []byte("lease")): + // "lease 192.168.0.1 {" => "192.168.0.1" + s := string(bs) + l.ip = net.ParseIP(s[6 : len(s)-2]) + case !l.hasIP() && bytes.HasPrefix(bs, []byte("iaaddr")): + // "iaaddr 1985:470:1f0b:c9a::001 {" => "1985:470:1f0b:c9a::001" + s := string(bs) + l.ip = net.ParseIP(s[7 : len(s)-2]) + case l.hasIP() && !l.hasBindingState() && bytes.HasPrefix(bs, []byte("binding state")): + // "binding state active;" => "active" + s := string(bs) + l.bindingState = s[14 : len(s)-1] + case bytes.HasPrefix(bs, []byte("}")): + if l.hasIP() && l.hasBindingState() { + leasesSet[l.ip.String()] = l + } + l = leaseEntry{} + } + } + + if len(leasesSet) == 0 { + return nil, nil + } + + leases := make([]leaseEntry, 0, len(leasesSet)) + for _, l := range leasesSet { + leases = append(leases, l) + } + return leases, nil +} |