-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdhcpreg.py
executable file
·142 lines (109 loc) · 4.06 KB
/
dhcpreg.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/python
####################
# DHCP Lease parser to find leases that haven't expired
# and pair them up with registered MAC addresses
#
# Contributers:
# James Jenkins (aka: themind)
####################
import re
import datetime
import json
import sys
import time
USERS_FILE = "registrations.config"
mac_patt = re.compile("hardware ethernet ([0-9A-Fa-f:]+?);")
lease_patt = re.compile("lease ([0-9\.]+?) {(.+?)}", re.DOTALL)
start_time_patt = re.compile("starts [0-9] ([0-9:/ ]+?);")
end_time_patt = re.compile("ends (?:[0-9] ([0-9:/ ]+?);|(never))")
def LoadRegistrations():
try:
with open(USERS_FILE, "r") as f:
users=json.load(f)
return users
except (IOError, ValueError):
return {}
def GetIgnoreMacs():
try:
with open("ignorelist.config","r") as f:
# Only return non-comment lines. Beginning of line must
# be a # (octothorpe) symbol
return filter(lambda line: not line.lstrip().startswith("#"), \
f.read().strip().split("\n"))
except IOError:
sys.stderr.write("No ignorelist.config file\n")
pass
return []
def RegisterMac(mac,name):
users = LoadRegistrations()
if not users.get(mac.lower(), None):
users[mac.lower()] = name
else:
return False
with open(USERS_FILE, "w") as f:
json.dump(users, f)
return True
def DeregisterMac(mac,nick):
try:
users = LoadRegistrations()
if users[mac]==nick:
del users[mac]
with open(USERS_FILE, "w") as f:
json.dump(users,f)
return True
except (IOError, ValueError, KeyError):
# Just let the error drop through and return False
pass
return False
def LookupMac(mac):
try:
users = LoadRegistrations()
return users[mac.lower()]
except KeyError:
return None
def LookupNick(nick):
users = LoadRegistrations()
macs = []
for mac, reg_nick in users.iteritems():
if reg_nick == nick:
macs.append(mac)
return macs
def GetActive(fp):
data = fp.read()
now = datetime.datetime.utcnow()
ignore_macs = GetIgnoreMacs()
active_users = []
other_macs = []
utc_hours_offset = ((time.daylight and time.altzone) or time.timezone)/60/60
utc_offset = datetime.timedelta(0, 0, 0, 0, 0, utc_hours_offset, 0)
# Loop through leases in the leases file found by the regex
for lease in lease_patt.findall(data):
# Find the end time for the lease and convert it to a useable datetime
end_time_s = end_time_patt.search(lease[1]).group(1)
end_time = None
if end_time_s and end_time_s != "never":
end_time = datetime.datetime.strptime(end_time_s, "%Y/%m/%d %H:%M:%S")
# Check that we haven't reached the end of this lease
# make sure to account for UTC offset
if end_time is None or now < end_time:
# Pull the mac address from the lease with a regex
lease_mac_address = mac_patt.findall(lease[1])
# Make sure the regex actually found a mac address. Sometimes
# a lease doesn't have one, so just ignore and skip to next one
if not lease_mac_address:
continue
# regex.findall returns a list we just want the zeroth item
lease_mac_address = lease_mac_address[0]
if lease_mac_address not in ignore_macs:
user = LookupMac(lease_mac_address)
# If a registered user was found and not alreay active from
# some other lease (possibly a secondary device).
if user and user not in active_users:
active_users.append(user)
# Keep track of non-registered mac addresses
elif not user and lease_mac_address not in other_macs:
other_macs.append(lease_mac_address)
return (active_users,other_macs)
if __name__ == "__main__":
with open("/var/dhcpd/var/db/dhcpd.leases") as f:
print GetActive(f)