1#
2# dhcpd_leases_parser.py
3#
4# Copyright 2008, Paul McGuire
5#
6# Sample parser to parse a dhcpd.leases file to extract leases
7# and lease attributes
8#
9# format ref: http://www.linuxmanpages.com/man5/dhcpd.leases.5.php
10#
11
12sample = r"""\
13# All times in this file are in UTC (GMT), not your local timezone.   This is
14# not a bug, so please don't ask about it.   There is no portable way to
15# store leases in the local timezone, so please don't request this as a
16# feature.   If this is inconvenient or confusing to you, we sincerely
17# apologize.   Seriously, though - don't ask.
18# The format of this file is documented in the dhcpd.leases(5) manual page.
19# This lease file was written by isc-dhcp-V3.0.4
20
21lease 192.168.0.250 {
22  starts 3 2008/01/23 17:16:41;
23  ends 6 2008/02/02 17:16:41;
24  tstp 6 2008/02/02 17:16:41;
25  binding state free;
26  hardware ethernet 00:17:f2:9b:d8:19;
27  uid "\001\000\027\362\233\330\031";
28}
29lease 192.168.0.198 {
30  starts 1 2008/02/04 13:46:55;
31  ends never;
32  tstp 1 2008/02/04 17:04:14;
33  binding state free;
34  hardware ethernet 00:13:72:d3:3b:98;
35  uid "\001\000\023r\323;\230";
36}
37lease 192.168.0.239 {
38  starts 3 2008/02/06 12:12:03;
39  ends 4 2008/02/07 12:12:03;
40  tstp 4 2008/02/07 12:12:03;
41  binding state free;
42  hardware ethernet 00:1d:09:65:93:26;
43}
44"""
45
46from pyparsing import *
47import datetime,time
48
49LBRACE,RBRACE,SEMI,QUOTE = map(Suppress,'{};"')
50ipAddress = Combine(Word(nums) + ('.' + Word(nums))*3)
51hexint = Word(hexnums,exact=2)
52macAddress = Combine(hexint + (':'+hexint)*5)
53hdwType = Word(alphanums)
54
55yyyymmdd = Combine((Word(nums,exact=4)|Word(nums,exact=2))+
56                    ('/'+Word(nums,exact=2))*2)
57hhmmss = Combine(Word(nums,exact=2)+(':'+Word(nums,exact=2))*2)
58dateRef = oneOf(list("0123456"))("weekday") + yyyymmdd("date") + \
59                                                        hhmmss("time")
60
61def utcToLocalTime(tokens):
62    utctime = datetime.datetime.strptime("%(date)s %(time)s" % tokens,
63                                                    "%Y/%m/%d %H:%M:%S")
64    localtime = utctime-datetime.timedelta(0,time.timezone,0)
65    tokens["utcdate"],tokens["utctime"] = tokens["date"],tokens["time"]
66    tokens["localdate"],tokens["localtime"] = str(localtime).split()
67    del tokens["date"]
68    del tokens["time"]
69dateRef.setParseAction(utcToLocalTime)
70
71startsStmt = "starts" + dateRef + SEMI
72endsStmt = "ends" + (dateRef | "never") + SEMI
73tstpStmt = "tstp" + dateRef + SEMI
74tsfpStmt = "tsfp" + dateRef + SEMI
75hdwStmt = "hardware" + hdwType("type") + macAddress("mac") + SEMI
76uidStmt = "uid" + QuotedString('"')("uid") + SEMI
77bindingStmt = "binding" + Word(alphanums) + Word(alphanums) + SEMI
78
79leaseStatement = startsStmt | endsStmt | tstpStmt | tsfpStmt | hdwStmt | \
80                                                        uidStmt | bindingStmt
81leaseDef = "lease" + ipAddress("ipaddress") + LBRACE + \
82                            Dict(ZeroOrMore(Group(leaseStatement))) + RBRACE
83
84for lease in leaseDef.searchString(sample):
85    print(lease.dump())
86    print(lease.ipaddress,'->',lease.hardware.mac)
87    print()
88