Project

General

Profile

Download (14.5 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	status_dhcp_leases.php
5
	Copyright (C) 2013-2015 Electric Sheep Fencing, LP
6
	Copyright (C) 2004-2009 Scott Ullrich
7
	All rights reserved.
8

    
9
	originally 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-dhcpleases
42
##|*NAME=Status: DHCP leases page
43
##|*DESCR=Allow access to the 'Status: DHCP leases' page.
44
##|*MATCH=status_dhcp_leases.php*
45
##|-PRIV
46

    
47
require("guiconfig.inc");
48
require_once("config.inc");
49

    
50
$pgtitle = array(gettext("Status"),gettext("DHCP leases"));
51
$shortcut_section = "dhcp";
52

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

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

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

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

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

    
88
include("head.inc");
89

    
90
?>
91

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

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

    
100
function adjust_gmt($dt) {
101
	global $config;
102
	$dhcpd = $config['dhcpd'];
103
	foreach ($dhcpd as $dhcpditem) {
104
		$dhcpleaseinlocaltime = $dhcpditem['dhcpleaseinlocaltime'];
105
		if ($dhcpleaseinlocaltime == "yes")
106
			break;
107
	}
108
	if ($dhcpleaseinlocaltime == "yes") {
109
		$ts = strtotime($dt . " GMT");
110
		return strftime("%Y/%m/%d %I:%M:%S%p", $ts);
111
	} else
112
		return $dt;
113
}
114

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

    
125
$awk = "/usr/bin/awk";
126
/* this pattern sticks comments into a single array item */
127
$cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'";
128
/* We then split the leases file by } */
129
$splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'";
130

    
131
/* stuff the leases file in a proper format into a array by line */
132
exec("/bin/cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content);
133
$leases_count = count($leases_content);
134
exec("/usr/sbin/arp -an", $rawdata);
135
$arpdata_ip = array();
136
$arpdata_mac = array();
137
foreach ($rawdata as $line) {
138
	$elements = explode(' ',$line);
139
	if ($elements[3] != "(incomplete)") {
140
		$arpent = array();
141
		$arpdata_ip[] = trim(str_replace(array('(',')'),'',$elements[1]));
142
		$arpdata_mac[] = strtolower(trim($elements[3]));
143
	}
144
}
145
unset($rawdata);
146
$pools = array();
147
$leases = array();
148
$i = 0;
149
$l = 0;
150
$p = 0;
151

    
152
// Put everything together again
153
foreach($leases_content as $lease) {
154
	/* split the line by space */
155
	$data = explode(" ", $lease);
156
	/* walk the fields */
157
	$f = 0;
158
	$fcount = count($data);
159
	/* with less than 20 fields there is nothing useful */
160
	if($fcount < 20) {
161
		$i++;
162
		continue;
163
	}
164
	while($f < $fcount) {
165
		switch($data[$f]) {
166
			case "failover":
167
				$pools[$p]['name'] = trim($data[$f+2], '"');
168
				$pools[$p]['name'] = "{$pools[$p]['name']} (" . convert_friendly_interface_to_friendly_descr(substr($pools[$p]['name'], 5)) . ")";
169
				$pools[$p]['mystate'] = $data[$f+7];
170
				$pools[$p]['peerstate'] = $data[$f+14];
171
				$pools[$p]['mydate'] = $data[$f+10];
172
				$pools[$p]['mydate'] .= " " . $data[$f+11];
173
				$pools[$p]['peerdate'] = $data[$f+17];
174
				$pools[$p]['peerdate'] .= " " . $data[$f+18];
175
				$p++;
176
				$i++;
177
				continue 3;
178
			case "lease":
179
				$leases[$l]['ip'] = $data[$f+1];
180
				$leases[$l]['type'] = "dynamic";
181
				$f = $f+2;
182
				break;
183
			case "starts":
184
				$leases[$l]['start'] = $data[$f+2];
185
				$leases[$l]['start'] .= " " . $data[$f+3];
186
				$f = $f+3;
187
				break;
188
			case "ends":
189
				$leases[$l]['end'] = $data[$f+2];
190
				$leases[$l]['end'] .= " " . $data[$f+3];
191
				$f = $f+3;
192
				break;
193
			case "tstp":
194
				$f = $f+3;
195
				break;
196
			case "tsfp":
197
				$f = $f+3;
198
				break;
199
			case "atsfp":
200
				$f = $f+3;
201
				break;
202
			case "cltt":
203
				$f = $f+3;
204
				break;
205
			case "binding":
206
				switch($data[$f+2]) {
207
					case "active":
208
						$leases[$l]['act'] = "active";
209
						break;
210
					case "free":
211
						$leases[$l]['act'] = "expired";
212
						$leases[$l]['online'] = "offline";
213
						break;
214
					case "backup":
215
						$leases[$l]['act'] = "reserved";
216
						$leases[$l]['online'] = "offline";
217
						break;
218
				}
219
				$f = $f+1;
220
				break;
221
			case "next":
222
				/* skip the next binding statement */
223
				$f = $f+3;
224
				break;
225
			case "rewind":
226
				/* skip the rewind binding statement */
227
				$f = $f+3;
228
				break;
229
			case "hardware":
230
				$leases[$l]['mac'] = $data[$f+2];
231
				/* check if it's online and the lease is active */
232
				if (in_array($leases[$l]['ip'], $arpdata_ip)) {
233
					$leases[$l]['online'] = 'online';
234
				} else {
235
					$leases[$l]['online'] = 'offline';
236
				}
237
				$f = $f+2;
238
				break;
239
			case "client-hostname":
240
				if($data[$f+1] <> "") {
241
					$leases[$l]['hostname'] = preg_replace('/"/','',$data[$f+1]);
242
				} else {
243
					$hostname = gethostbyaddr($leases[$l]['ip']);
244
					if($hostname <> "") {
245
						$leases[$l]['hostname'] = $hostname;
246
					}
247
				}
248
				$f = $f+1;
249
				break;
250
			case "uid":
251
				$f = $f+1;
252
				break;
253
		}
254
		$f++;
255
	}
256
	$l++;
257
	$i++;
258
	/* slowly chisel away at the source array */
259
	array_shift($leases_content);
260
}
261
/* remove the old array */
262
unset($lease_content);
263

    
264
/* remove duplicate items by mac address */
265
if(count($leases) > 0) {
266
	$leases = remove_duplicate($leases,"ip");
267
}
268

    
269
if(count($pools) > 0) {
270
	$pools = remove_duplicate($pools,"name");
271
	asort($pools);
272
}
273

    
274
foreach($config['interfaces'] as $ifname => $ifarr) {
275
	if (is_array($config['dhcpd'][$ifname]) &&
276
		is_array($config['dhcpd'][$ifname]['staticmap'])) {
277
		$staticmap_array_index = 0;
278
		foreach($config['dhcpd'][$ifname]['staticmap'] as $static) {
279
			$slease = array();
280
			$slease['ip'] = $static['ipaddr'];
281
			$slease['type'] = "static";
282
			$slease['mac'] = $static['mac'];
283
			$slease['if'] = $ifname;
284
			$slease['start'] = "";
285
			$slease['end'] = "";
286
			$slease['hostname'] = htmlentities($static['hostname']);
287
			$slease['act'] = "static";
288
			$slease['online'] = in_array(strtolower($slease['mac']), $arpdata_mac) ? 'online' : 'offline';
289
			$slease['staticmap_array_index'] = $staticmap_array_index;
290
			$leases[] = $slease;
291
			$staticmap_array_index++;
292
		}
293
	}
294
}
295

    
296
if ($_GET['order'])
297
	usort($leases, "leasecmp");
298

    
299
/* only print pool status when we have one */
300
if(count($pools) > 0) {
301
?>
302
<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0" summary="dhcp leases">
303
  <tr>
304
    <td class="listhdrr"><?=gettext("Failover Group"); ?></a></td>
305
    <td class="listhdrr"><?=gettext("My State"); ?></a></td>
306
    <td class="listhdrr"><?=gettext("Since"); ?></a></td>
307
    <td class="listhdrr"><?=gettext("Peer State"); ?></a></td>
308
    <td class="listhdrr"><?=gettext("Since"); ?></a></td>
309
  </tr>
310
<?php
311
foreach ($pools as $data) {
312
	echo "<tr>\n";
313
	echo "<td class=\"listlr\">{$fspans}{$data['name']}{$fspane}</td>\n";
314
	echo "<td class=\"listr\">{$fspans}{$data['mystate']}{$fspane}</td>\n";
315
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['mydate']) . "{$fspane}</td>\n";
316
	echo "<td class=\"listr\">{$fspans}{$data['peerstate']}{$fspane}</td>\n";
317
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['peerdate']) . "{$fspane}</td>\n";
318
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
319
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
320
	echo "</tr>\n";
321
}
322

    
323
?>
324
</table>
325

    
326
<?php
327
/* only print pool status when we have one */
328
}
329
?>
330

    
331
<br/>
332

    
333
<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0" summary="dhcp leases">
334
  <tr>
335
    <td class="listhdrr"><a href="#"><?=gettext("IP address"); ?></a></td>
336
    <td class="listhdrr"><a href="#"><?=gettext("MAC address"); ?></a></td>
337
    <td class="listhdrr"><a href="#"><?=gettext("Hostname"); ?></a></td>
338
    <td class="listhdrr"><a href="#"><?=gettext("Start"); ?></a></td>
339
    <td class="listhdrr"><a href="#"><?=gettext("End"); ?></a></td>
340
    <td class="listhdrr"><a href="#"><?=gettext("Online"); ?></a></td>
341
    <td class="listhdrr"><a href="#"><?=gettext("Lease Type"); ?></a></td>
342
	</tr>
343
<?php
344
// Load MAC-Manufacturer table
345
$mac_man = load_mac_manufacturer_table();
346
foreach ($leases as $data) {
347
	if (($data['act'] == "active") || ($data['act'] == "static") || ($_GET['all'] == 1)) {
348
		if ($data['act'] != "active" && $data['act'] != "static") {
349
			$fspans = "<span class=\"gray\">";
350
			$fspane = "&nbsp;</span>";
351
		} else {
352
			$fspans = "";
353
			$fspane = "&nbsp;";
354
		}
355
		$lip = ip2ulong($data['ip']);
356
		if ($data['act'] != "static") {
357
			foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
358
				if (!is_array($dhcpifconf['range']))
359
					continue;
360
				if (($lip >= ip2ulong($dhcpifconf['range']['from'])) && ($lip <= ip2ulong($dhcpifconf['range']['to']))) {
361
					$data['if'] = $dhcpif;
362
					break;
363
				}
364
			}
365
		}
366
		echo "<tr>\n";
367
		echo "<td class=\"listlr\">{$fspans}{$data['ip']}{$fspane}</td>\n";
368
		$mac=$data['mac'];
369
		$mac_hi = strtoupper($mac[0] . $mac[1] . $mac[3] . $mac[4] . $mac[6] . $mac[7]);
370
		if ($data['online'] != "online") {
371
			if(isset($mac_man[$mac_hi])){ // Manufacturer for this MAC is defined
372
				echo "<td class=\"listr\">{$fspans}<a href=\"services_wol.php?if={$data['if']}&amp;mac=$mac\" title=\"" . gettext("$mac - send Wake on LAN packet to this MAC address") ."\">{$mac}</a><br /><font size=\"-2\"><i>{$mac_man[$mac_hi]}</i></font>{$fspane}</td>\n";
373
			} else {
374
				echo "<td class=\"listr\">{$fspans}<a href=\"services_wol.php?if={$data['if']}&amp;mac={$data['mac']}\" title=\"" . gettext("send Wake on LAN packet to this MAC address") ."\">{$data['mac']}</a>{$fspane}</td>\n";
375
			}
376
		} else {
377
			if(isset($mac_man[$mac_hi])){ // Manufacturer for this MAC is defined
378
				echo "<td class=\"listr\">{$fspans}{$mac}<br /><font size=\"-2\"><i>{$mac_man[$mac_hi]}</i></font>{$fspane}</td>\n";
379
			} else {
380
				echo "<td class=\"listr\">{$fspans}{$data['mac']}{$fspane}</td>\n";
381
			}
382
		}
383
		echo "<td class=\"listr\">{$fspans}"  . htmlentities($data['hostname']) . "{$fspane}</td>\n";
384
		if ($data['type'] != "static") {
385
			echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['start']) . "{$fspane}</td>\n";
386
			echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['end']) . "{$fspane}</td>\n";
387
		} else {
388
			echo "<td class=\"listr\">{$fspans} n/a {$fspane}</td>\n";
389
			echo "<td class=\"listr\">{$fspans} n/a {$fspane}</td>\n";
390
		}
391
		echo "<td class=\"listr\">{$fspans}{$data['online']}{$fspane}</td>\n";
392
		echo "<td class=\"listr\">{$fspans}{$data['act']}{$fspane}</td>\n";
393
		echo "<td valign=\"middle\">&nbsp;";
394
		if ($data['type'] == "dynamic") {
395
			echo "<a href=\"services_dhcp_edit.php?if={$data['if']}&amp;mac={$data['mac']}&amp;hostname={$data['hostname']}\">";
396
			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") ."\" alt=\"add\" /></a>&nbsp;\n";
397
		} else {
398
			echo "<a href=\"services_dhcp_edit.php?if={$data['if']}&amp;id={$data['staticmap_array_index']}\">";
399
			echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_e.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("edit the static mapping for this entry") ."\" alt=\"add\" />&nbsp;\n";
400
		}
401

    
402
		echo "<a href=\"services_wol_edit.php?if={$data['if']}&amp;mac={$data['mac']}&amp;descr={$data['hostname']}\">";
403
		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") ."\" alt=\"add\" /></a>&nbsp;\n";
404

    
405
		/* Only show the button for offline dynamic leases */
406
		if (($data['type'] == "dynamic") && ($data['online'] != "online")) {
407
			echo "<a href=\"status_dhcp_leases.php?deleteip={$data['ip']}&amp;all=" . htmlspecialchars($_GET['all']) . "\">";
408
			echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("delete this DHCP lease") . "\" alt=\"delete\" /></a>&nbsp;\n";
409
		}
410
	echo "</td></tr>\n";
411
	}
412
}
413

    
414
?>
415
</table>
416
<br/>
417
<form action="status_dhcp_leases.php" method="get">
418
<input type="hidden" name="order" value="<?=htmlspecialchars($_GET['order']);?>" />
419
<?php if ($_GET['all']): ?>
420
<input type="hidden" name="all" value="0" />
421
<input type="submit" class="formbtn" value="<?=gettext("Show active and static leases only"); ?>" />
422
<?php else: ?>
423
<input type="hidden" name="all" value="1" />
424
<input type="submit" class="formbtn" value="<?=gettext("Show all configured leases"); ?>" />
425
<?php endif; ?>
426
</form>
427
<?php if($leases == 0): ?>
428
<p><strong><?=gettext("No leases file found. Is the DHCP server active"); ?>?</strong></p>
429
<?php endif; ?>
430

    
431
<?php include("fend.inc"); ?>
432
</body>
433
</html>
(185-185/256)