Browse Source

from talos, fixed

Jared Dunbar 1 year ago
parent
commit
6bfc230a7f
Signed by: Jared Dunbar <jrddunbr@gmail.com> GPG Key ID: CF202CC859BAC692
1 changed files with 260 additions and 0 deletions
  1. 260
    0
      index.py

+ 260
- 0
index.py View File

@@ -0,0 +1,260 @@
1
+#!/usr/bin/python3
2
+
3
+import datetime, bisect
4
+
5
+print("Content-type: text/html")
6
+print("")
7
+
8
+
9
+# Below code copied from a script from a forgotten source on the internet.
10
+
11
+
12
+def parse_timestamp(raw_str):
13
+    tokens = raw_str.split()
14
+    if len(tokens) == 1:
15
+        if tokens[0].lower() == 'never':
16
+            return 'never';
17
+        else:
18
+            raise Exception('Parse error in timestamp')
19
+    elif len(tokens) == 3:
20
+        return datetime.datetime.strptime(' '.join(tokens[1:]),
21
+            '%Y/%m/%d %H:%M:%S')
22
+    else:
23
+        raise Exception('Parse error in timestamp')
24
+
25
+def timestamp_is_ge(t1, t2):
26
+    if type(t2) == type(""):
27
+        return False
28
+    if t1 == 'never':
29
+        return True
30
+    elif t2 == 'never':
31
+        return False
32
+    else:
33
+        return t1 >= t2
34
+
35
+def timestamp_is_lt(t1, t2):
36
+    if type(t2) == type(""):
37
+        return t1 != 'never'
38
+    if t1 == 'never':
39
+        return False
40
+    elif t2 == 'never':
41
+        return t1 != 'never'
42
+    else:
43
+        return t1 < t2
44
+
45
+def timestamp_is_between(t, tstart, tend):
46
+    return timestamp_is_ge(t, tstart) and timestamp_is_lt(t, tend)
47
+
48
+def parse_hardware(raw_str):
49
+    tokens = raw_str.split()
50
+    if len(tokens) == 2:
51
+        return tokens[1]
52
+    else:
53
+        raise Exception('Parse error in hardware')
54
+
55
+def strip_endquotes(raw_str):
56
+    return raw_str.strip('"')
57
+
58
+def identity(raw_str):
59
+    return raw_str
60
+
61
+def parse_binding_state(raw_str):
62
+    tokens = raw_str.split()
63
+    if len(tokens) == 2:
64
+        return tokens[1]
65
+    else:
66
+        raise Exception('Parse error in binding state')
67
+
68
+def parse_next_binding_state(raw_str):
69
+    tokens = raw_str.split()
70
+    if len(tokens) == 3:
71
+        return tokens[2]
72
+    else:
73
+        raise Exception('Parse error in next binding state')
74
+
75
+def parse_rewind_binding_state(raw_str):
76
+    tokens = raw_str.split()
77
+    if len(tokens) == 3:
78
+        return tokens[2]
79
+    else:
80
+        raise Exception('Parse error in next binding state')
81
+
82
+def parse_leases_file(leases_file):
83
+    valid_keys = {
84
+        'starts':               parse_timestamp,
85
+        'ends':                 parse_timestamp,
86
+        'tstp':                 parse_timestamp,
87
+        'tsfp':                 parse_timestamp,
88
+        'atsfp':                parse_timestamp,
89
+        'cltt':                 parse_timestamp,
90
+        'hardware':             parse_hardware,
91
+        'binding':              parse_binding_state,
92
+        'next':                 parse_next_binding_state,
93
+        'rewind':               parse_rewind_binding_state,
94
+        'uid':                  strip_endquotes,
95
+        'client-hostname':      strip_endquotes,
96
+        'option':               identity,
97
+        'set':                  identity,
98
+        'on':                   identity,
99
+        'abandoned':            None,
100
+        'bootp':                None,
101
+        'reserved':             None,
102
+        }
103
+    leases_db = {}
104
+    lease_rec = {}
105
+    in_lease = False
106
+    in_failover = False
107
+    for line in leases_file:
108
+        if line.lstrip().startswith('#'):
109
+            continue
110
+        tokens = line.split()
111
+        if len(tokens) == 0:
112
+            continue
113
+        key = tokens[0].lower()
114
+        if key == 'lease':
115
+            if not in_lease:
116
+                ip_address = tokens[1]
117
+                lease_rec = {'ip_address' : ip_address}
118
+                in_lease = True
119
+            else:
120
+                raise Exception('Parse error in leases file')
121
+        elif key == 'failover':
122
+            in_failover = True
123
+        elif key == '}':
124
+            if in_lease:
125
+                for k in valid_keys:
126
+                    if callable(valid_keys[k]):
127
+                        lease_rec[k] = lease_rec.get(k, '')
128
+                    else:
129
+                        lease_rec[k] = False
130
+                ip_address = lease_rec['ip_address']
131
+                if ip_address in leases_db:
132
+                    leases_db[ip_address].insert(0, lease_rec)
133
+                else:
134
+                    leases_db[ip_address] = [lease_rec]
135
+                lease_rec = {}
136
+                in_lease = False
137
+            elif in_failover:
138
+                in_failover = False
139
+                continue
140
+            else:
141
+                raise Exception('Parse error in leases file')
142
+        elif key in valid_keys:
143
+            if in_lease:
144
+                value = line[(line.index(key) + len(key)):]
145
+                value = value.strip().rstrip(';').rstrip()
146
+                if callable(valid_keys[key]):
147
+                    lease_rec[key] = valid_keys[key](value)
148
+                else:
149
+                    lease_rec[key] = True
150
+            else:
151
+                raise Exception('Parse error in leases file')
152
+        else:
153
+            if in_lease:
154
+                raise Exception('Parse error in leases file')
155
+    if in_lease:
156
+        raise Exception('Parse error in leases file')
157
+    return leases_db
158
+
159
+def round_timedelta(tdelta):
160
+    return datetime.timedelta(tdelta.days,
161
+        tdelta.seconds + (0 if tdelta.microseconds < 500000 else 1))
162
+
163
+def timestamp_now():
164
+    n = datetime.datetime.utcnow()
165
+    return datetime.datetime(n.year, n.month, n.day, n.hour, n.minute,
166
+        n.second + (0 if n.microsecond < 500000 else 1))
167
+
168
+def lease_is_active(lease_rec, as_of_ts):
169
+    return timestamp_is_between(as_of_ts, lease_rec['starts'],
170
+        lease_rec['ends'])
171
+
172
+def ipv4_to_int(ipv4_addr):
173
+    parts = ipv4_addr.split('.')
174
+    return (int(parts[0]) << 24) + (int(parts[1]) << 16) + \
175
+        (int(parts[2]) << 8) + int(parts[3])
176
+
177
+def select_active_leases(leases_db, as_of_ts):
178
+    retarray = []
179
+    sortedarray = []
180
+    for ip_address in leases_db:
181
+        lease_rec = leases_db[ip_address][0]
182
+        if lease_is_active(lease_rec, as_of_ts):
183
+            ip_as_int = ipv4_to_int(ip_address)
184
+            insertpos = bisect.bisect(sortedarray, ip_as_int)
185
+            sortedarray.insert(insertpos, ip_as_int)
186
+            retarray.insert(insertpos, lease_rec)
187
+    return retarray
188
+
189
+
190
+# End of the other code
191
+#############################
192
+
193
+# Searches for insert segments in the HTML code, ex: <!-- INSERT X HERE -->
194
+def insert_item(text, search, insert):
195
+    parts = text.split(search, 1)
196
+    # If this is 2 parts, then we have a split string. Otherwise, bail.
197
+    if len(parts) == 1:
198
+        return text
199
+    else:
200
+        before = parts[0].rsplit("<!--", 1)[0]
201
+        after = parts[1].split("-->", 1)[1]
202
+        return before + insert + after
203
+
204
+###############################
205
+
206
+try:
207
+    #myfile = open('leases.leases','r')
208
+    myfile = open('/var/lib/dhcp/dhcpd.leases', 'r')
209
+    leases = parse_leases_file(myfile)
210
+    myfile.close()
211
+
212
+    now = timestamp_now()
213
+    report_dataset = select_active_leases(leases, now)
214
+
215
+
216
+    # read in the index file, and place it in idx
217
+    idx_file = open("index-src.html")
218
+    idx = ""
219
+    for line in idx_file:
220
+        idx += line + "\n"
221
+
222
+    # Done reading in the file. Now to parse and replace, and return, if success
223
+
224
+    repl = ""
225
+
226
+    for lease in report_dataset:
227
+        try:
228
+            if lease['ends'] != 'never':
229
+                expires = str(lease['ends'] - now)
230
+            repl += "<tr><td>"
231
+            repl += lease['ip_address']
232
+            repl += "</td><td>"
233
+            repl += lease['hardware']
234
+            repl += "</td><td>"
235
+            if lease['ends'] == 'never':
236
+                repl += "never"
237
+            else:
238
+                repl += str(lease['ends'] - now)
239
+            repl += "</td><td>"
240
+            repl += lease['client-hostname']
241
+            repl += "</td></tr>\n"
242
+        except:
243
+            pass
244
+
245
+    active = str(len(report_dataset))
246
+    report_gen = str(now)
247
+
248
+    stats = "<h4>Total active leases: {}</h4><h4>Report generated {}</h4>".format(active, report_gen)
249
+
250
+    idx = insert_item(idx, "INSERT LEASE TABLE", repl)
251
+    idx = insert_item(idx, "INSERT STATS", stats)
252
+    print (idx)
253
+
254
+
255
+except Exception as e:
256
+    print("<html><body>")
257
+    print("There was an error on the server end. We are sorry.")
258
+    print("Perhaps try the <a href=\"index-src.html\">static version</a> of this page.")
259
+    print("The error encountered is listed below: <br/><br/>{}<br/>".format(str(e).replace("\n", "<br/>")))
260
+    print("</body></html>")

Loading…
Cancel
Save