Project

General

Profile

Download (15 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

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

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

    
57
	/* Read existing leases */
58
	$leases_contents = file($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_dhcp_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
	global $config; 
99
	$dhcpd = $config['dhcpd'];
100
	foreach ($dhcpd as $dhcpleaseinlocaltime) {
101
		$dhcpleaseinlocaltime = $dhcpleaseinlocaltime['dhcpleaseinlocaltime'];
102
		if ($dhcpleaseinlocaltime == "yes") 
103
			break;
104
	}
105
	$timezone = $config['system']['timezone'];
106
	$ts = strtotime($dt . " GMT");
107
	if ($dhcpleaseinlocaltime == "yes") {
108
		$this_tz = new DateTimeZone($timezone); 
109
		$dhcp_lt = new DateTime(strftime("%I:%M:%S%p", $ts), $this_tz); 
110
		$offset = $this_tz->getOffset($dhcp_lt);
111
		$ts = $ts + $offset;
112
		return strftime("%Y/%m/%d %I:%M:%S%p", $ts);
113
	}
114
	else
115
		return strftime("%Y/%m/%d %H:%M:%S", $ts);
116
}
117

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

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

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

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

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

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

    
277
foreach($config['interfaces'] as $ifname => $ifarr) {
278
	if (is_array($config['dhcpd'][$ifname]) && 
279
		is_array($config['dhcpd'][$ifname]['staticmap'])) {
280
		foreach($config['dhcpd'][$ifname]['staticmap'] as $static) {
281
			$slease = array();
282
			$slease['ip'] = $static['ipaddr'];
283
			$slease['type'] = "static";
284
			$slease['mac'] = $static['mac'];
285
			$slease['start'] = "";
286
			$slease['end'] = "";
287
			$slease['hostname'] = htmlentities($static['hostname']);
288
			$slease['act'] = "static";
289
			$online = exec("/usr/sbin/arp -an |/usr/bin/grep {$slease['mac']}| /usr/bin/wc -l|/usr/bin/awk '{print $1;}'");
290
			if ($online == 1) {
291
				$slease['online'] = 'online';
292
			} else {
293
				$slease['online'] = 'offline';
294
			}
295
			$leases[] = $slease;
296
		}
297
	}
298
}
299

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

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

    
327
?>
328
</table>
329

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

    
335
<p>
336

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

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

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

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

    
446
<?php include("fend.inc"); ?>
447
</body>
448
</html>
(170-170/240)