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 = array();
141
foreach ($rawdata as $line) {
142
	$elements = explode(' ',$line);
143
	if ($elements[3] != "(incomplete)") {
144
		$arpent = array();
145
		$arpent['ip'] = trim(str_replace(array('(',')'),'',$elements[1]));
146
		// $arpent['mac'] = trim($elements[3]);
147
		// $arpent['interface'] = trim($elements[5]);
148
	$arpdata[] = $arpent['ip'];
149
	}
150
}
151
unset($rawdata);
152
$pools = array();
153
$leases = array();
154
$i = 0;
155
$l = 0;
156
$p = 0;
157

    
158
// Put everything together again
159
foreach($leases_content as $lease) {
160
	/* split the line by space */
161
	$data = explode(" ", $lease);
162
	/* walk the fields */
163
	$f = 0;
164
	$fcount = count($data);
165
	/* with less then 20 fields there is nothing useful */
166
	if($fcount < 20) {
167
		$i++;
168
		continue;
169
	}
170
	while($f < $fcount) {
171
		switch($data[$f]) {
172
			case "failover":
173
				$pools[$p]['name'] = $data[$f+2];
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)) {
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
			$online = exec("/usr/sbin/arp -an |/usr/bin/grep {$slease['mac']}| /usr/bin/wc -l|/usr/bin/awk '{print $1;}'");
292
			if ($online == 1) {
293
				$slease['online'] = 'online';
294
			} else {
295
				$slease['online'] = 'offline';
296
			}
297
			$leases[] = $slease;
298
		}
299
	}
300
}
301

    
302
if ($_GET['order'])
303
	usort($leases, "leasecmp");
304

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

    
329
?>
330
</table>
331

    
332
<?php
333
/* only print pool status when we have one */
334
}
335
?>
336

    
337
<p>
338

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

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

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

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

    
450
<?php include("fend.inc"); ?>
451
</body>
452
</html>
(176-176/246)