Project

General

Profile

Download (15.2 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	status_dhcp_leases.php
5
	Copyright (C) 2004-2009 Scott Ullrich
6
	All rights reserved.
7

    
8
	originially part of m0n0wall (http://m0n0.ch/wall)
9
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
10
	All rights reserved.
11

    
12
	Redistribution and use in source and binary forms, with or without
13
	modification, are permitted provided that the following conditions are met:
14

    
15
	1. Redistributions of source code must retain the above copyright notice,
16
	   this list of conditions and the following disclaimer.
17

    
18
	2. Redistributions in binary form must reproduce the above copyright
19
	   notice, this list of conditions and the following disclaimer in the
20
	   documentation and/or other materials provided with the distribution.
21

    
22
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
26
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
	POSSIBILITY OF SUCH DAMAGE.
32
*/
33

    
34
/*
35
	pfSense_BUILDER_BINARIES:	/usr/bin/awk	/bin/cat	/usr/sbin/arp	/usr/bin/wc	/usr/bin/grep
36
	pfSense_MODULE:	dhcpserver
37
*/
38

    
39
##|+PRIV
40
##|*IDENT=page-status-dhcpleases
41
##|*NAME=Status: DHCP leases page
42
##|*DESCR=Allow access to the 'Status: DHCP leases' page.
43
##|*MATCH=status_dhcp_leases.php*
44
##|-PRIV
45

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

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

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

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

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

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

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

    
87
include("head.inc");
88

    
89
?>
90

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

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

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

    
120
function remove_duplicate($array, $field)
121
{
122
  foreach ($array as $sub)
123
   $cmp[] = $sub[$field];
124
  $unique = array_unique(array_reverse($cmp,true));
125
  foreach ($unique as $k => $rien)
126
   $new[] = $array[$k];
127
  return $new;
128
}
129

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

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

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

    
269
/* remove duplicate items by mac address */
270
if(count($leases) > 0) {
271
	$leases = remove_duplicate($leases,"ip");
272
}
273

    
274
if(count($pools) > 0) {
275
	$pools = remove_duplicate($pools,"name");
276
	asort($pools);
277
}
278

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

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

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

    
324
?>
325
</table>
326

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

    
332
<p>
333

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

    
416
                echo "<td valign=\"middle\"><a href=\"services_wol_edit.php?if={$data['if']}&mac={$data['mac']}&descr={$data['hostname']}\">";
417
		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";
418

    
419
		/* Only show the button for offline dynamic leases */
420
		if (($data['type'] == "dynamic") && ($data['online'] != "online")) {
421
			echo "<td class=\"list\" valign=\"middle\"><a href=\"status_dhcp_leases.php?deleteip={$data['ip']}&all=" . htmlspecialchars($_GET['all']) . "\">";
422
			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";
423
		}
424
                echo "</tr>\n";
425
	}
426
}
427

    
428
?>
429
</table>
430
<p>
431
<form action="status_dhcp_leases.php" method="get">
432
<input type="hidden" name="order" value="<?=htmlspecialchars($_GET['order']);?>">
433
<?php if ($_GET['all']): ?>
434
<input type="hidden" name="all" value="0">
435
<input type="submit" class="formbtn" value="<?=gettext("Show active and static leases only"); ?>">
436
<?php else: ?>
437
<input type="hidden" name="all" value="1">
438
<input type="submit" class="formbtn" value="<?=gettext("Show all configured leases"); ?>">
439
<?php endif; ?>
440
</form>
441
<?php if($leases == 0): ?>
442
<p><strong><?=gettext("No leases file found. Is the DHCP server active"); ?>?</strong></p>
443
<?php endif; ?>
444

    
445
<?php include("fend.inc"); ?>
446
</body>
447
</html>
(176-176/246)