Project

General

Profile

Download (14.5 KB) Statistics
| Branch: | Tag: | Revision:
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/ndp	/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
require_once("config.inc");
49

    
50
$pgtitle = array(gettext("Status"),gettext("DHCPv6 leases"));
51

    
52
$leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd6.leases";
53

    
54
if (($_GET['deleteip']) && (is_ipaddr($_GET['deleteip']))) {
55
	/* Stop DHCPD */
56
	killbyname("dhcpd");
57

    
58
	/* Read existing leases */
59
	$leases_contents = explode("\n", file_get_contents($leasesfile));
60
	$newleases_contents = array();
61
	$i=0;
62
	while ($i < count($leases_contents)) {
63
		/* Find the lease(s) we want to delete */
64
		if ($leases_contents[$i] == "lease {$_GET['deleteip']} {") {
65
			/* Skip to the end of the lease declaration */
66
			do {
67
				$i++;
68
			} while ($leases_contents[$i] != "}");
69
		} else {
70
			/* It's a line we want to keep, copy it over. */
71
			$newleases_contents[] = $leases_contents[$i];
72
		}
73
		$i++;
74
	}
75

    
76
	/* Write out the new leases file */
77
	$fd = fopen($leasesfile, 'w');
78
	fwrite($fd, implode("\n", $newleases_contents));
79
	fclose($fd);
80

    
81
	/* Restart DHCP Service */
82
	services_dhcpd_configure();
83
	header("Location: status_dhcpv6_leases.php?all={$_GET['all']}");
84
}
85

    
86
include("head.inc");
87

    
88
?>
89

    
90
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
91
<?php include("fbegin.inc"); ?>
92
<?php
93

    
94
function leasecmp($a, $b) {
95
	return strcmp($a[$_GET['order']], $b[$_GET['order']]);
96
}
97

    
98
function adjust_gmt($dt) {
99
	global $config;
100
	$sysctl = $config['system'];
101
	$timezone = $sysctl['timezone'];
102
	$timeformatchangev6 = $sysctl['timeformatchangev6'];
103
	$ts = strtotime($dt . " GMT");
104
	if ($timeformatchangev6 == "yes") {
105
		$this_tz = new DateTimeZone($timezone); 
106
		$dhcp_lt = new DateTime(strftime("%I:%M:%S%p", $ts), $this_tz); 
107
		$offset = $this_tz->getOffset($dhcp_lt);
108
		$ts = $ts + $offset;
109
		return strftime("%Y/%m/%d %I:%M:%S%p", $ts);
110
        }
111
	else
112
		return strftime("%Y/%m/%d %H:%M:%S", $ts);
113
}
114

    
115
function remove_duplicate($array, $field) {
116
	foreach ($array as $sub)
117
		$cmp[] = $sub[$field];
118
	$unique = array_unique(array_reverse($cmp,true));
119
	foreach ($unique as $k => $rien)
120
		$new[] = $array[$k];
121
	return $new;
122
}
123

    
124
function parse_duid($duid_string) {
125
	$parsed_duid = array();
126
	for ($i=0; $i < strlen($duid_string); $i++) {
127
		$s = substr($duid_string, $i, 1);
128
		if ($s == '\\') {
129
			$n = substr($duid_string, $i+1, 1);
130
			if (($n == '\\') || ($n == '"')) {
131
				$parsed_duid[] = sprintf("%02x", ord($n));
132
			} elseif (is_numeric($n)) {
133
				$parsed_duid[] = sprintf("%02x", octdec(substr($duid_string, $i+1, 3)));
134
				$i += 3;
135
			}
136
		} else {
137
			$parsed_duid[] = sprintf("%02x", ord($s));
138
		}
139
	}
140
	$iaid = array_slice($parsed_duid, 0, 4);
141
	$duid = array_slice($parsed_duid, 4);
142
	return array($iaid, $duid);
143
}
144

    
145
$awk = "/usr/bin/awk";
146

    
147
/* this pattern sticks comments into a single array item */
148
$cleanpattern = "'{ gsub(\"^#.*\", \"\");} { gsub(\"^server-duid.*\", \"\");} { gsub(\";\", \"\"); print;}'";
149
/* We then split the leases file by } */
150
$splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'";
151

    
152
/* stuff the leases file in a proper format into a array by line */
153
exec("/bin/cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern} | /usr/bin/grep '^ia-na'", $leases_content);
154
$leases_count = count($leases_content);
155
exec("/usr/sbin/ndp -an", $rawdata);
156
$ndpdata = array();
157
foreach ($rawdata as $line) {
158
	$elements = preg_split('/\s+/ ',$line);
159
	if ($elements[1] != "(incomplete)") {
160
		$ndpent = array();
161
		$ip = trim(str_replace(array('(',')'),'',$elements[0]));
162
		$ndpent['mac'] = trim($elements[1]);
163
		$ndpent['interface'] = trim($elements[2]);
164
		$ndpdata[$ip] = $ndpent;
165
	}
166
}
167

    
168
$pools = array();
169
$leases = array();
170
$i = 0;
171
$l = 0;
172
$p = 0;
173

    
174
// Put everything together again
175
while($i < $leases_count) {
176
	/* split the line by space */
177
	$duid_split = array();
178
	preg_match('/ia-na "(.*)" { (.*)/ ', $leases_content[$i], $duid_split);
179
	if (!empty($duid_split[1])) {
180
		$iaid_duid = parse_duid($duid_split[1]);
181
		$leases[$l]['iaid'] = hexdec(implode("", array_reverse($iaid_duid[0])));
182
		$leases[$l]['duid'] = implode(":", $iaid_duid[1]);
183
		$data = explode(" ", $duid_split[2]);
184
	} else {
185
		$data = explode(" ", $leases_content[$i]);
186
	}
187
	/* walk the fields */
188
	$f = 0;
189
	$fcount = count($data);
190
	/* with less then 12 fields there is nothing useful */
191
	if($fcount < 12) {
192
		$i++;
193
		continue;
194
	}
195
	while($f < $fcount) {
196
		switch($data[$f]) {
197
			case "failover":
198
				$pools[$p]['name'] = $data[$f+2];
199
				$pools[$p]['mystate'] = $data[$f+7];
200
				$pools[$p]['peerstate'] = $data[$f+14];
201
				$pools[$p]['mydate'] = $data[$f+10];
202
				$pools[$p]['mydate'] .= " " . $data[$f+11];
203
				$pools[$p]['peerdate'] = $data[$f+17];
204
				$pools[$p]['peerdate'] .= " " . $data[$f+18];
205
				$p++;
206
				$i++;
207
				continue 3;
208
			case "ia-na":
209
				if ($data[$f+1][0] == '"') {
210
					$duid = "";
211
					/* FIXME: This needs a safety belt to prevent an infinite loop */
212
					while ($data[$f][strlen($data[$f])-1] != '"') {
213
						$duid .= " " . $data[$f+1];
214
						$f++;
215
					}
216
					$leases[$l]['duid'] = $duid;
217
				} else {
218
					$leases[$l]['duid'] = $data[$f+1];
219
				}
220
				$leases[$l]['type'] = "dynamic";
221
				$f = $f+2;
222
				break;
223
			case "iaaddr":
224
				$leases[$l]['ip'] = $data[$f+1];
225
				$leases[$l]['type'] = "dynamic";
226
				if (in_array($leases[$l]['ip'], array_keys($ndpdata))) {
227
					$leases[$l]['online'] = 'online';
228
				} else {
229
					$leases[$l]['online'] = 'offline';
230
				}
231
				$f = $f+2;
232
				break;
233
			case "starts":
234
				$leases[$l]['start'] = $data[$f+2];
235
				$leases[$l]['start'] .= " " . $data[$f+3];
236
				$f = $f+3;
237
				break;
238
			case "ends":
239
				$leases[$l]['end'] = $data[$f+2];
240
				$leases[$l]['end'] .= " " . $data[$f+3];
241
				$f = $f+3;
242
				break;
243
			case "tstp":
244
				$f = $f+3;
245
				break;
246
			case "tsfp":
247
				$f = $f+3;
248
				break;
249
			case "atsfp":
250
				$f = $f+3;
251
				break;
252
			case "cltt":
253
				$leases[$l]['start'] = $data[$f+2];
254
				$leases[$l]['start'] .= " " . $data[$f+3];
255
				$f = $f+3;
256
				break;
257
			case "binding":
258
				switch($data[$f+2]) {
259
					case "active":
260
						$leases[$l]['act'] = "active";
261
						break;
262
					case "free":
263
						$leases[$l]['act'] = "expired";
264
						$leases[$l]['online'] = "offline";
265
						break;
266
					case "backup":
267
						$leases[$l]['act'] = "reserved";
268
						$leases[$l]['online'] = "offline";
269
						break;
270
				}
271
				$f = $f+1;
272
				break;
273
			case "next":
274
				/* skip the next binding statement */
275
				$f = $f+3;
276
				break;
277
			case "hardware":
278
				$f = $f+2;
279
				break;
280
			case "client-hostname":
281
				if($data[$f+1] <> "") {
282
					$leases[$l]['hostname'] = preg_replace('/"/','',$data[$f+1]);
283
				} else {
284
					$hostname = gethostbyaddr($leases[$l]['ip']);
285
					if($hostname <> "") {
286
						$leases[$l]['hostname'] = $hostname;
287
					}
288
				}
289
				$f = $f+1;
290
				break;
291
			case "uid":
292
				$f = $f+1;
293
				break;
294
		}
295
		$f++;
296
	}
297
	$l++;
298
	$i++;
299
}
300

    
301
if(count($leases) > 0) {
302
	$leases = remove_duplicate($leases,"ip");
303
}
304

    
305
if(count($pools) > 0) {
306
	$pools = remove_duplicate($pools,"name");
307
	asort($pools);
308
}
309

    
310
foreach($config['interfaces'] as $ifname => $ifarr) {
311
	if (is_array($config['dhcpdv6'][$ifname]) && 
312
		is_array($config['dhcpdv6'][$ifname]['staticmap'])) {
313
		foreach($config['dhcpdv6'][$ifname]['staticmap'] as $static) {
314
			$slease = array();
315
			$slease['ip'] = $static['ipaddrv6'];
316
			$slease['type'] = "static";
317
			$slease['duid'] = $static['duid'];
318
			$slease['start'] = "";
319
			$slease['end'] = "";
320
			$slease['hostname'] = htmlentities($static['hostname']);
321
			$slease['act'] = "static";
322
			if (in_array($slease['ip'], array_keys($ndpdata))) {
323
				$slease['online'] = 'online';
324
			} else {
325
				$slease['online'] = 'offline';
326
			}
327

    
328
			$leases[] = $slease;
329
		}
330
	}
331
}
332

    
333
if ($_GET['order'])
334
	usort($leases, "leasecmp");
335

    
336
/* only print pool status when we have one */
337
if(count($pools) > 0) {
338
?>
339
<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
340
  <tr>
341
    <td class="listhdrr"><?=gettext("Failover Group"); ?></a></td>
342
    <td class="listhdrr"><?=gettext("My State"); ?></a></td>
343
    <td class="listhdrr"><?=gettext("Since"); ?></a></td>
344
    <td class="listhdrr"><?=gettext("Peer State"); ?></a></td>
345
    <td class="listhdrr"><?=gettext("Since"); ?></a></td>
346
  </tr>
347
<?php
348
foreach ($pools as $data) {
349
	echo "<tr>\n";
350
	echo "<td class=\"listlr\">{$fspans}{$data['name']}{$fspane}&nbsp;</td>\n";
351
	echo "<td class=\"listr\">{$fspans}{$data['mystate']}{$fspane}&nbsp;</td>\n";
352
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['mydate']) . "{$fspane}&nbsp;</td>\n";
353
	echo "<td class=\"listr\">{$fspans}{$data['peerstate']}{$fspane}&nbsp;</td>\n";
354
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['peerdate']) . "{$fspane}&nbsp;</td>\n";
355
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
356
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
357
	echo "</tr>\n";
358
}
359

    
360
?>
361
</table>
362

    
363
<?php
364
/* only print pool status when we have one */
365
}
366
?>
367

    
368
<p>
369

    
370
<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
371
  <tr>
372
    <td class="listhdrr"><a href="#"><?=gettext("IPv6 address"); ?></a></td>
373
    <td class="listhdrr"><a href="#"><?=gettext("IAID"); ?></a></td>
374
    <td class="listhdrr"><a href="#"><?=gettext("DUID"); ?></a></td>
375
    <td class="listhdrr"><a href="#"><?=gettext("Hostname/MAC"); ?></a></td>
376
    <td class="listhdrr"><a href="#"><?=gettext("Start"); ?></a></td>
377
    <td class="listhdrr"><a href="#"><?=gettext("End"); ?></a></td>
378
    <td class="listhdrr"><a href="#"><?=gettext("Online"); ?></a></td>
379
    <td class="listhdrr"><a href="#"><?=gettext("Lease Type"); ?></a></td>
380
	</tr>
381
<?php
382
foreach ($leases as $data) {
383
	if (($data['act'] == "active") || ($data['act'] == "static") || ($_GET['all'] == 1)) {
384
		if ($data['act'] != "active" && $data['act'] != "static") {
385
			$fspans = "<span class=\"gray\">";
386
			$fspane = "</span>";
387
		} else {
388
			$fspans = $fspane = "";
389
		}
390

    
391
		if ($data['act'] == "static") {
392
			foreach ($config['dhcpdv6'] as $dhcpif => $dhcpifconf) {
393
				if(is_array($dhcpifconf['staticmap'])) {
394
					foreach ($dhcpifconf['staticmap'] as $staticent) {
395
						if ($data['ip'] == $staticent['ipaddr']) {
396
							$data['if'] = $dhcpif;
397
							break;
398
						}
399
					}
400
				}
401
				/* exit as soon as we have an interface */
402
				if ($data['if'] != "")
403
					break;
404
			}
405
		} else {
406
			$data['if'] = convert_real_interface_to_friendly_interface_name(guess_interface_from_ip($data['ip']));
407
                }		
408
		echo "<tr>\n";
409
                echo "<td class=\"listlr\">{$fspans}{$data['ip']}{$fspane}&nbsp;</td>\n";
410
		echo "<td class=\"listr\">{$fspans}{$data['iaid']}{$fspane}&nbsp;</td>\n";
411
		echo "<td class=\"listr\">{$fspans}{$data['duid']}{$fspane}&nbsp;</td>\n";
412
		echo "<td class=\"listr\">{$fspans}";
413
		if (!empty($data['hostname'])) {
414
			echo htmlentities($data['hostname']) . "<br/>";
415
		}
416
		echo htmlentities($ndpdata[$data['ip']]['mac']);
417
		echo "{$fspane}&nbsp;</td>\n";
418
				if ($data['type'] != "static") {
419
					echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['start']) . "{$fspane}&nbsp;</td>\n";
420
					echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['end']) . "{$fspane}&nbsp;</td>\n";
421
				} else {
422
					echo "<td class=\"listr\">{$fspans} n/a {$fspane}&nbsp;</td>\n";
423
					echo "<td class=\"listr\">{$fspans} n/a {$fspane}&nbsp;</td>\n";
424
				}
425
                echo "<td class=\"listr\">{$fspans}{$data['online']}{$fspane}&nbsp;</td>\n";
426
                echo "<td class=\"listr\">{$fspans}{$data['act']}{$fspane}&nbsp;</td>\n";
427
		
428
		if ($data['type'] == "dynamic") {
429
			echo "<td valign=\"middle\"><a href=\"services_dhcpv6_edit.php?if={$data['if']}&duid={$data['duid']}&hostname={$data['hostname']}\">";
430
			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";
431
		} else {
432
                	echo "<td class=\"list\" valign=\"middle\">";
433
			echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus_mo.gif\" width=\"17\" height=\"17\" border=\"0\"></td>\n";
434
		}
435

    
436
		/* Only show the button for offline dynamic leases */
437
		if (($data['type'] == "dynamic") && ($data['online'] != "online")) {
438
			echo "<td class=\"list\" valign=\"middle\"><a href=\"status_dhcpv6_leases.php?deleteip={$data['ip']}&all=" . htmlspecialchars($_GET['all']) . "\">";
439
			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";
440
		}
441
                echo "</tr>\n";
442
	}
443
}
444

    
445
?>
446
</table>
447
<p>
448
<form action="status_dhcpv6_leases.php" method="GET">
449
<input type="hidden" name="order" value="<?=htmlspecialchars($_GET['order']);?>">
450
<?php if ($_GET['all']): ?>
451
<input type="hidden" name="all" value="0">
452
<input type="submit" class="formbtn" value="<?=gettext("Show active and static leases only"); ?>">
453
<?php else: ?>
454
<input type="hidden" name="all" value="1">
455
<input type="submit" class="formbtn" value="<?=gettext("Show all configured leases"); ?>">
456
<?php endif; ?>
457
</form>
458
<?php if($leases == 0): ?>
459
<p><strong><?=gettext("No leases file found. Is the DHCP server active"); ?>?</strong></p>
460
<?php endif; ?>
461

    
462
<?php include("fend.inc"); ?>
463
</body>
464
</html>
(171-171/239)