github.com/netdata/go.d.plugin@v0.58.1/modules/isc_dhcpd/parse.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package isc_dhcpd 4 5 import ( 6 "bufio" 7 "bytes" 8 "net" 9 "os" 10 ) 11 12 /* 13 Documentation (v4.4): https://kb.isc.org/docs/en/isc-dhcp-44-manual-pages-dhcpdleases 14 15 DHCPv4 prepare declaration: 16 prepare ip-address { 17 statements... 18 } 19 20 DHCPv6 prepare declaration: 21 ia_ta IAID_DUID { 22 cltt date; 23 iaaddr ipv6-address { 24 statements... 25 } 26 } 27 ia_na IAID_DUID { 28 cltt date; 29 iaaddr ipv6-address { 30 statements... 31 } 32 } 33 ia_pd IAID_DUID { 34 cltt date; 35 iaprefix ipv6-address/prefix-length { 36 statements... 37 } 38 } 39 */ 40 41 type leaseEntry struct { 42 ip net.IP 43 bindingState string 44 } 45 46 func (l leaseEntry) hasIP() bool { return l.ip != nil } 47 func (l leaseEntry) hasBindingState() bool { return l.bindingState != "" } 48 49 func parseDHCPdLeasesFile(filepath string) ([]leaseEntry, error) { 50 f, err := os.Open(filepath) 51 if err != nil { 52 return nil, err 53 } 54 defer func() { _ = f.Close() }() 55 56 leasesSet := make(map[string]leaseEntry) 57 l := leaseEntry{} 58 sc := bufio.NewScanner(f) 59 60 for sc.Scan() { 61 bs := bytes.TrimSpace(sc.Bytes()) 62 switch { 63 case !l.hasIP() && bytes.HasPrefix(bs, []byte("lease")): 64 // "lease 192.168.0.1 {" => "192.168.0.1" 65 s := string(bs) 66 l.ip = net.ParseIP(s[6 : len(s)-2]) 67 case !l.hasIP() && bytes.HasPrefix(bs, []byte("iaaddr")): 68 // "iaaddr 1985:470:1f0b:c9a::001 {" => "1985:470:1f0b:c9a::001" 69 s := string(bs) 70 l.ip = net.ParseIP(s[7 : len(s)-2]) 71 case l.hasIP() && !l.hasBindingState() && bytes.HasPrefix(bs, []byte("binding state")): 72 // "binding state active;" => "active" 73 s := string(bs) 74 l.bindingState = s[14 : len(s)-1] 75 case bytes.HasPrefix(bs, []byte("}")): 76 if l.hasIP() && l.hasBindingState() { 77 leasesSet[l.ip.String()] = l 78 } 79 l = leaseEntry{} 80 } 81 } 82 83 if len(leasesSet) == 0 { 84 return nil, nil 85 } 86 87 leases := make([]leaseEntry, 0, len(leasesSet)) 88 for _, l := range leasesSet { 89 leases = append(leases, l) 90 } 91 return leases, nil 92 }