Revision c1640267
Added by Seth Mos over 14 years ago
usr/local/www/status_dhcpv6_leases.php | ||
---|---|---|
1 |
<?php |
|
2 |
/* $Id$ */ |
|
3 |
/* |
|
4 |
status_dhcpv6_leases.php |
|
5 |
Copyright (C) 2004-2009 Scott Ullrich |
|
6 |
Copyright (C) 2011 Seth Mos |
|
7 |
All rights reserved. |
|
8 |
|
|
9 |
originially part of m0n0wall (http://m0n0.ch/wall) |
|
10 |
Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. |
|
11 |
All rights reserved. |
|
12 |
|
|
13 |
Redistribution and use in source and binary forms, with or without |
|
14 |
modification, are permitted provided that the following conditions are met: |
|
15 |
|
|
16 |
1. Redistributions of source code must retain the above copyright notice, |
|
17 |
this list of conditions and the following disclaimer. |
|
18 |
|
|
19 |
2. Redistributions in binary form must reproduce the above copyright |
|
20 |
notice, this list of conditions and the following disclaimer in the |
|
21 |
documentation and/or other materials provided with the distribution. |
|
22 |
|
|
23 |
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
|
24 |
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
|
25 |
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
|
26 |
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
|
27 |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
28 |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
29 |
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
30 |
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
31 |
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
32 |
POSSIBILITY OF SUCH DAMAGE. |
|
33 |
*/ |
|
34 |
|
|
35 |
/* |
|
36 |
pfSense_BUILDER_BINARIES: /usr/bin/awk /bin/cat /usr/sbin/arp /usr/bin/wc /usr/bin/grep |
|
37 |
pfSense_MODULE: dhcpserver |
|
38 |
*/ |
|
39 |
|
|
40 |
##|+PRIV |
|
41 |
##|*IDENT=page-status-dhcpv6leases |
|
42 |
##|*NAME=Status: DHCPv6 leases page |
|
43 |
##|*DESCR=Allow access to the 'Status: DHCPv6 leases' page. |
|
44 |
##|*MATCH=status_dhcpv6_leases.php* |
|
45 |
##|-PRIV |
|
46 |
|
|
47 |
require("guiconfig.inc"); |
|
48 |
|
|
49 |
$pgtitle = array(gettext("Status"),gettext("DHCPv6 leases")); |
|
50 |
|
|
51 |
$leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases"; |
|
52 |
|
|
53 |
if (($_GET['deleteip']) && (is_ipaddr($_GET['deleteip']))) { |
|
54 |
/* Stop DHCPD */ |
|
55 |
killbyname("dhcpd"); |
|
56 |
|
|
57 |
/* Read existing leases */ |
|
58 |
$leases_contents = explode("\n", file_get_contents($leasesfile)); |
|
59 |
$newleases_contents = array(); |
|
60 |
$i=0; |
|
61 |
while ($i < count($leases_contents)) { |
|
62 |
/* Find the lease(s) we want to delete */ |
|
63 |
if ($leases_contents[$i] == "lease {$_GET['deleteip']} {") { |
|
64 |
/* Skip to the end of the lease declaration */ |
|
65 |
do { |
|
66 |
$i++; |
|
67 |
} while ($leases_contents[$i] != "}"); |
|
68 |
} else { |
|
69 |
/* It's a line we want to keep, copy it over. */ |
|
70 |
$newleases_contents[] = $leases_contents[$i]; |
|
71 |
} |
|
72 |
$i++; |
|
73 |
} |
|
74 |
|
|
75 |
/* Write out the new leases file */ |
|
76 |
$fd = fopen($leasesfile, 'w'); |
|
77 |
fwrite($fd, implode("\n", $newleases_contents)); |
|
78 |
fclose($fd); |
|
79 |
|
|
80 |
/* Restart DHCP Service */ |
|
81 |
services_dhcpd_configure(); |
|
82 |
header("Location: status_dhcpv6_leases.php?all={$_GET['all']}"); |
|
83 |
} |
|
84 |
|
|
85 |
include("head.inc"); |
|
86 |
|
|
87 |
?> |
|
88 |
|
|
89 |
<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> |
|
90 |
<?php include("fbegin.inc"); ?> |
|
91 |
<?php |
|
92 |
|
|
93 |
function leasecmp($a, $b) { |
|
94 |
return strcmp($a[$_GET['order']], $b[$_GET['order']]); |
|
95 |
} |
|
96 |
|
|
97 |
function adjust_gmt($dt) { |
|
98 |
$ts = strtotime($dt . " GMT"); |
|
99 |
return strftime("%Y/%m/%d %H:%M:%S", $ts); |
|
100 |
} |
|
101 |
|
|
102 |
function remove_duplicate($array, $field) |
|
103 |
{ |
|
104 |
foreach ($array as $sub) |
|
105 |
$cmp[] = $sub[$field]; |
|
106 |
$unique = array_unique(array_reverse($cmp,true)); |
|
107 |
foreach ($unique as $k => $rien) |
|
108 |
$new[] = $array[$k]; |
|
109 |
return $new; |
|
110 |
} |
|
111 |
|
|
112 |
$awk = "/usr/bin/awk"; |
|
113 |
/* this pattern sticks comments into a single array item */ |
|
114 |
$cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'"; |
|
115 |
/* We then split the leases file by } */ |
|
116 |
$splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'"; |
|
117 |
|
|
118 |
/* stuff the leases file in a proper format into a array by line */ |
|
119 |
exec("/bin/cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content); |
|
120 |
$leases_count = count($leases_content); |
|
121 |
exec("/usr/sbin/arp -an", $rawdata); |
|
122 |
$arpdata = array(); |
|
123 |
foreach ($rawdata as $line) { |
|
124 |
$elements = explode(' ',$line); |
|
125 |
if ($elements[3] != "(incomplete)") { |
|
126 |
$arpent = array(); |
|
127 |
$arpent['ip'] = trim(str_replace(array('(',')'),'',$elements[1])); |
|
128 |
// $arpent['mac'] = trim($elements[3]); |
|
129 |
// $arpent['interface'] = trim($elements[5]); |
|
130 |
$arpdata[] = $arpent['ip']; |
|
131 |
} |
|
132 |
} |
|
133 |
|
|
134 |
$pools = array(); |
|
135 |
$leases = array(); |
|
136 |
$i = 0; |
|
137 |
$l = 0; |
|
138 |
$p = 0; |
|
139 |
|
|
140 |
// Put everything together again |
|
141 |
while($i < $leases_count) { |
|
142 |
/* split the line by space */ |
|
143 |
$data = explode(" ", $leases_content[$i]); |
|
144 |
/* walk the fields */ |
|
145 |
$f = 0; |
|
146 |
$fcount = count($data); |
|
147 |
/* with less then 20 fields there is nothing useful */ |
|
148 |
if($fcount < 20) { |
|
149 |
$i++; |
|
150 |
continue; |
|
151 |
} |
|
152 |
while($f < $fcount) { |
|
153 |
switch($data[$f]) { |
|
154 |
case "failover": |
|
155 |
$pools[$p]['name'] = $data[$f+2]; |
|
156 |
$pools[$p]['mystate'] = $data[$f+7]; |
|
157 |
$pools[$p]['peerstate'] = $data[$f+14]; |
|
158 |
$pools[$p]['mydate'] = $data[$f+10]; |
|
159 |
$pools[$p]['mydate'] .= " " . $data[$f+11]; |
|
160 |
$pools[$p]['peerdate'] = $data[$f+17]; |
|
161 |
$pools[$p]['peerdate'] .= " " . $data[$f+18]; |
|
162 |
$p++; |
|
163 |
$i++; |
|
164 |
continue 3; |
|
165 |
case "lease": |
|
166 |
$leases[$l]['ip'] = $data[$f+1]; |
|
167 |
$leases[$l]['type'] = "dynamic"; |
|
168 |
$f = $f+2; |
|
169 |
break; |
|
170 |
case "starts": |
|
171 |
$leases[$l]['start'] = $data[$f+2]; |
|
172 |
$leases[$l]['start'] .= " " . $data[$f+3]; |
|
173 |
$f = $f+3; |
|
174 |
break; |
|
175 |
case "ends": |
|
176 |
$leases[$l]['end'] = $data[$f+2]; |
|
177 |
$leases[$l]['end'] .= " " . $data[$f+3]; |
|
178 |
$f = $f+3; |
|
179 |
break; |
|
180 |
case "tstp": |
|
181 |
$f = $f+3; |
|
182 |
break; |
|
183 |
case "tsfp": |
|
184 |
$f = $f+3; |
|
185 |
break; |
|
186 |
case "atsfp": |
|
187 |
$f = $f+3; |
|
188 |
break; |
|
189 |
case "cltt": |
|
190 |
$f = $f+3; |
|
191 |
break; |
|
192 |
case "binding": |
|
193 |
switch($data[$f+2]) { |
|
194 |
case "active": |
|
195 |
$leases[$l]['act'] = "active"; |
|
196 |
break; |
|
197 |
case "free": |
|
198 |
$leases[$l]['act'] = "expired"; |
|
199 |
$leases[$l]['online'] = "offline"; |
|
200 |
break; |
|
201 |
case "backup": |
|
202 |
$leases[$l]['act'] = "reserved"; |
|
203 |
$leases[$l]['online'] = "offline"; |
|
204 |
break; |
|
205 |
} |
|
206 |
$f = $f+1; |
|
207 |
break; |
|
208 |
case "next": |
|
209 |
/* skip the next binding statement */ |
|
210 |
$f = $f+3; |
|
211 |
break; |
|
212 |
case "hardware": |
|
213 |
$leases[$l]['mac'] = $data[$f+2]; |
|
214 |
/* check if it's online and the lease is active */ |
|
215 |
if (in_array($leases[$l]['ip'], $arpdata)) { |
|
216 |
$leases[$l]['online'] = 'online'; |
|
217 |
} else { |
|
218 |
$leases[$l]['online'] = 'offline'; |
|
219 |
} |
|
220 |
$f = $f+2; |
|
221 |
break; |
|
222 |
case "client-hostname": |
|
223 |
if($data[$f+1] <> "") { |
|
224 |
$leases[$l]['hostname'] = preg_replace('/"/','',$data[$f+1]); |
|
225 |
} else { |
|
226 |
$hostname = gethostbyaddr($leases[$l]['ip']); |
|
227 |
if($hostname <> "") { |
|
228 |
$leases[$l]['hostname'] = $hostname; |
|
229 |
} |
|
230 |
} |
|
231 |
$f = $f+1; |
|
232 |
break; |
|
233 |
case "uid": |
|
234 |
$f = $f+1; |
|
235 |
break; |
|
236 |
} |
|
237 |
$f++; |
|
238 |
} |
|
239 |
$l++; |
|
240 |
$i++; |
|
241 |
} |
|
242 |
|
|
243 |
/* remove duplicate items by mac address */ |
|
244 |
if(count($leases) > 0) { |
|
245 |
$leases = remove_duplicate($leases,"ip"); |
|
246 |
} |
|
247 |
|
|
248 |
if(count($pools) > 0) { |
|
249 |
$pools = remove_duplicate($pools,"name"); |
|
250 |
asort($pools); |
|
251 |
} |
|
252 |
|
|
253 |
foreach($config['interfaces'] as $ifname => $ifarr) { |
|
254 |
if (is_array($config['dhcpdv6'][$ifname]) && |
|
255 |
is_array($config['dhcpdv6'][$ifname]['staticmap'])) { |
|
256 |
foreach($config['dhcpdv6'][$ifname]['staticmap'] as $static) { |
|
257 |
$slease = array(); |
|
258 |
$slease['ipv6'] = $static['ipaddr']; |
|
259 |
$slease['type'] = "static"; |
|
260 |
$slease['mac'] = $static['mac']; |
|
261 |
$slease['start'] = ""; |
|
262 |
$slease['end'] = ""; |
|
263 |
$slease['hostname'] = htmlentities($static['hostname']); |
|
264 |
$slease['act'] = "static"; |
|
265 |
$online = exec("/usr/sbin/arp -an |/usr/bin/grep {$slease['mac']}| /usr/bin/wc -l|/usr/bin/awk '{print $1;}'"); |
|
266 |
if ($online == 1) { |
|
267 |
$slease['online'] = 'online'; |
|
268 |
} else { |
|
269 |
$slease['online'] = 'offline'; |
|
270 |
} |
|
271 |
$leases[] = $slease; |
|
272 |
} |
|
273 |
} |
|
274 |
} |
|
275 |
|
|
276 |
if ($_GET['order']) |
|
277 |
usort($leases, "leasecmp"); |
|
278 |
|
|
279 |
/* only print pool status when we have one */ |
|
280 |
if(count($pools) > 0) { |
|
281 |
?> |
|
282 |
<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0"> |
|
283 |
<tr> |
|
284 |
<td class="listhdrr"><?=gettext("Failover Group"); ?></a></td> |
|
285 |
<td class="listhdrr"><?=gettext("My State"); ?></a></td> |
|
286 |
<td class="listhdrr"><?=gettext("Since"); ?></a></td> |
|
287 |
<td class="listhdrr"><?=gettext("Peer State"); ?></a></td> |
|
288 |
<td class="listhdrr"><?=gettext("Since"); ?></a></td> |
|
289 |
</tr> |
|
290 |
<?php |
|
291 |
foreach ($pools as $data) { |
|
292 |
echo "<tr>\n"; |
|
293 |
echo "<td class=\"listlr\">{$fspans}{$data['name']}{$fspane} </td>\n"; |
|
294 |
echo "<td class=\"listr\">{$fspans}{$data['mystate']}{$fspane} </td>\n"; |
|
295 |
echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['mydate']) . "{$fspane} </td>\n"; |
|
296 |
echo "<td class=\"listr\">{$fspans}{$data['peerstate']}{$fspane} </td>\n"; |
|
297 |
echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['peerdate']) . "{$fspane} </td>\n"; |
|
298 |
echo "<td class=\"list\" valign=\"middle\" width=\"17\"> </td>\n"; |
|
299 |
echo "<td class=\"list\" valign=\"middle\" width=\"17\"> </td>\n"; |
|
300 |
echo "</tr>\n"; |
|
301 |
} |
|
302 |
|
|
303 |
?> |
|
304 |
</table> |
|
305 |
|
|
306 |
<?php |
|
307 |
/* only print pool status when we have one */ |
|
308 |
} |
|
309 |
?> |
|
310 |
|
|
311 |
<p> |
|
312 |
|
|
313 |
<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0"> |
|
314 |
<tr> |
|
315 |
<td class="listhdrr"><a href="#"><?=gettext("IPv6 address"); ?></a></td> |
|
316 |
<td class="listhdrr"><a href="#"><?=gettext("MAC address"); ?></a></td> |
|
317 |
<td class="listhdrr"><a href="#"><?=gettext("Hostname"); ?></a></td> |
|
318 |
<td class="listhdrr"><a href="#"><?=gettext("Start"); ?></a></td> |
|
319 |
<td class="listhdrr"><a href="#"><?=gettext("End"); ?></a></td> |
|
320 |
<td class="listhdrr"><a href="#"><?=gettext("Online"); ?></a></td> |
|
321 |
<td class="listhdrr"><a href="#"><?=gettext("Lease Type"); ?></a></td> |
|
322 |
</tr> |
|
323 |
<?php |
|
324 |
foreach ($leases as $data) { |
|
325 |
if (($data['act'] == "active") || ($data['act'] == "static") || ($_GET['all'] == 1)) { |
|
326 |
if ($data['act'] != "active" && $data['act'] != "static") { |
|
327 |
$fspans = "<span class=\"gray\">"; |
|
328 |
$fspane = "</span>"; |
|
329 |
} else { |
|
330 |
$fspans = $fspane = ""; |
|
331 |
} |
|
332 |
// $lip = ip2ulong($data['ip']); |
|
333 |
if ($data['act'] == "static") { |
|
334 |
foreach ($config['dhcpdv6'] as $dhcpif => $dhcpifconf) { |
|
335 |
if(is_array($dhcpifconf['staticmap'])) { |
|
336 |
foreach ($dhcpifconf['staticmap'] as $staticent) { |
|
337 |
if ($data['ip'] == $staticent['ipaddr']) { |
|
338 |
$data['if'] = $dhcpif; |
|
339 |
break; |
|
340 |
} |
|
341 |
} |
|
342 |
} |
|
343 |
/* exit as soon as we have an interface */ |
|
344 |
if ($data['if'] != "") |
|
345 |
break; |
|
346 |
} |
|
347 |
} else { |
|
348 |
foreach ($config['dhcpdv6'] as $dhcpif => $dhcpifconf) { |
|
349 |
if (($lip >= ip2ulong($dhcpifconf['range']['from'])) && ($lip <= ip2ulong($dhcpifconf['range']['to']))) { |
|
350 |
$data['if'] = $dhcpif; |
|
351 |
break; |
|
352 |
} |
|
353 |
} |
|
354 |
} |
|
355 |
echo "<tr>\n"; |
|
356 |
echo "<td class=\"listlr\">{$fspans}{$data['ip']}{$fspane} </td>\n"; |
|
357 |
if ($data['online'] != "online") { |
|
358 |
echo "<td class=\"listr\">{$fspans}<a href=\"services_wol.php?if={$data['if']}&mac={$data['mac']}\" title=\"" . gettext("send Wake on LAN packet to this MAC address") ."\" onclick=\"return confirm('" . gettext("Send Wake on LAN packet to this MAC address?") . "')\">{$data['mac']}</a>{$fspane} </td>\n"; |
|
359 |
} else { |
|
360 |
echo "<td class=\"listr\">{$fspans}{$data['mac']}{$fspane} </td>\n"; |
|
361 |
} |
|
362 |
echo "<td class=\"listr\">{$fspans}" . htmlentities($data['hostname']) . "{$fspane} </td>\n"; |
|
363 |
if ($data['type'] != "static") { |
|
364 |
echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['start']) . "{$fspane} </td>\n"; |
|
365 |
echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['end']) . "{$fspane} </td>\n"; |
|
366 |
} else { |
|
367 |
echo "<td class=\"listr\">{$fspans} n/a {$fspane} </td>\n"; |
|
368 |
echo "<td class=\"listr\">{$fspans} n/a {$fspane} </td>\n"; |
|
369 |
} |
|
370 |
echo "<td class=\"listr\">{$fspans}{$data['online']}{$fspane} </td>\n"; |
|
371 |
echo "<td class=\"listr\">{$fspans}{$data['act']}{$fspane} </td>\n"; |
|
372 |
|
|
373 |
if ($data['type'] == "dynamic") { |
|
374 |
echo "<td valign=\"middle\"><a href=\"services_dhcp_edit.php?if={$data['if']}&mac={$data['mac']}&hostname={$data['hostname']}\">"; |
|
375 |
echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("add a static mapping for this MAC address") ."\"></a></td>\n"; |
|
376 |
} else { |
|
377 |
echo "<td class=\"list\" valign=\"middle\">"; |
|
378 |
echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus_mo.gif\" width=\"17\" height=\"17\" border=\"0\"></td>\n"; |
|
379 |
} |
|
380 |
|
|
381 |
echo "<td valign=\"middle\"><a href=\"services_wol_edit.php?if={$data['if']}&mac={$data['mac']}&descr={$data['hostname']}\">"; |
|
382 |
echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_wol_all.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("add a Wake on LAN mapping for this MAC address") ."\"></a></td>\n"; |
|
383 |
|
|
384 |
/* Only show the button for offline dynamic leases */ |
|
385 |
if (($data['type'] == "dynamic") && ($data['online'] != "online")) { |
|
386 |
echo "<td class=\"list\" valign=\"middle\"><a href=\"status_dhcp_leases.php?deleteip={$data['ip']}&all=" . htmlspecialchars($_GET['all']) . "\">"; |
|
387 |
echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("delete this DHCP lease") . "\"></a></td>\n"; |
|
388 |
} |
|
389 |
echo "</tr>\n"; |
|
390 |
} |
|
391 |
} |
|
392 |
|
|
393 |
?> |
|
394 |
</table> |
|
395 |
<p> |
|
396 |
<form action="status_dhcp_leases.php" method="GET"> |
|
397 |
<input type="hidden" name="order" value="<?=htmlspecialchars($_GET['order']);?>"> |
|
398 |
<?php if ($_GET['all']): ?> |
|
399 |
<input type="hidden" name="all" value="0"> |
|
400 |
<input type="submit" class="formbtn" value="<?=gettext("Show active and static leases only"); ?>"> |
|
401 |
<?php else: ?> |
|
402 |
<input type="hidden" name="all" value="1"> |
|
403 |
<input type="submit" class="formbtn" value="<?=gettext("Show all configured leases"); ?>"> |
|
404 |
<?php endif; ?> |
|
405 |
</form> |
|
406 |
<?php if($leases == 0): ?> |
|
407 |
<p><strong><?=gettext("No leases file found. Is the DHCP server active"); ?>?</strong></p> |
|
408 |
<?php endif; ?> |
|
409 |
|
|
410 |
<?php include("fend.inc"); ?> |
|
411 |
</body> |
|
412 |
</html> |
Also available in: Unified diff
Add the initial broken dhcp v6 leases page. I have no file to code it. Will wait for later.