Project

General

Profile

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

    
48
$pgtitle = array(gettext("Status"),gettext("DHCP leases"));
49

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

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

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

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

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

    
84
include("head.inc");
85

    
86
?>
87

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

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

    
96
function adjust_gmt($dt) {
97
        $ts = strtotime($dt . " GMT");
98
        return strftime("%Y/%m/%d %H:%M:%S", $ts);
99
}
100

    
101
function remove_duplicate($array, $field)
102
{
103
  foreach ($array as $sub)
104
   $cmp[] = $sub[$field];
105
  $unique = array_unique(array_reverse($cmp,true));
106
  foreach ($unique as $k => $rien)
107
   $new[] = $array[$k];
108
  return $new;
109
}
110

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

    
117
/* stuff the leases file in a proper format into a array by line */
118
exec("/bin/cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content);
119
$leases_count = count($leases_content);
120
exec("/usr/sbin/arp -an", $rawdata);
121
$arpdata = array();
122
foreach ($rawdata as $line) {
123
	$elements = explode(' ',$line);
124
	if ($elements[3] != "(incomplete)") {
125
		$arpent = array();
126
		$arpent['ip'] = trim(str_replace(array('(',')'),'',$elements[1]));
127
		// $arpent['mac'] = trim($elements[3]);
128
		// $arpent['interface'] = trim($elements[5]);
129
	$arpdata[] = $arpent['ip'];
130
	}
131
}
132

    
133
$pools = array();
134
$leases = array();
135
$i = 0;
136
$l = 0;
137
$p = 0;
138

    
139
// Put everything together again
140
while($i < $leases_count) {
141
	/* split the line by space */
142
	$data = explode(" ", $leases_content[$i]);
143
	/* walk the fields */
144
	$f = 0;
145
	$fcount = count($data);
146
	/* with less then 20 fields there is nothing useful */
147
	if($fcount < 20) {
148
		$i++;
149
		continue;
150
	}
151
	while($f < $fcount) {
152
		switch($data[$f]) {
153
			case "failover":
154
				$pools[$p]['name'] = $data[$f+2];
155
				$pools[$p]['mystate'] = $data[$f+7];
156
				$pools[$p]['peerstate'] = $data[$f+14];
157
				$pools[$p]['mydate'] = $data[$f+10];
158
				$pools[$p]['mydate'] .= " " . $data[$f+11];
159
				$pools[$p]['peerdate'] = $data[$f+17];
160
				$pools[$p]['peerdate'] .= " " . $data[$f+18];
161
				$p++;
162
				$i++;
163
				continue 3;
164
			case "lease":
165
				$leases[$l]['ip'] = $data[$f+1];
166
				$leases[$l]['type'] = "dynamic";
167
				$f = $f+2;
168
				break;
169
			case "starts":
170
				$leases[$l]['start'] = $data[$f+2];
171
				$leases[$l]['start'] .= " " . $data[$f+3];
172
				$f = $f+3;
173
				break;
174
			case "ends":
175
				$leases[$l]['end'] = $data[$f+2];
176
				$leases[$l]['end'] .= " " . $data[$f+3];
177
				$f = $f+3;
178
				break;
179
			case "tstp":
180
				$f = $f+3;
181
				break;
182
			case "tsfp":
183
				$f = $f+3;
184
				break;
185
			case "atsfp":
186
				$f = $f+3;
187
				break;
188
			case "cltt":
189
				$f = $f+3;
190
				break;
191
			case "binding":
192
				switch($data[$f+2]) {
193
					case "active":
194
						$leases[$l]['act'] = "active";
195
						break;
196
					case "free":
197
						$leases[$l]['act'] = "expired";
198
						$leases[$l]['online'] = "offline";
199
						break;
200
					case "backup":
201
						$leases[$l]['act'] = "reserved";
202
						$leases[$l]['online'] = "offline";
203
						break;
204
				}
205
				$f = $f+1;
206
				break;
207
			case "next":
208
				/* skip the next binding statement */
209
				$f = $f+3;
210
				break;
211
			case "rewind":
212
				/* skip the rewind binding statement */
213
				$f = $f+3;
214
				break;
215
			case "hardware":
216
				$leases[$l]['mac'] = $data[$f+2];
217
				/* check if it's online and the lease is active */
218
				if (in_array($leases[$l]['ip'], $arpdata)) {
219
					$leases[$l]['online'] = 'online';
220
				} else {
221
					$leases[$l]['online'] = 'offline';
222
				}
223
				$f = $f+2;
224
				break;
225
			case "client-hostname":
226
				if($data[$f+1] <> "") {
227
					$leases[$l]['hostname'] = preg_replace('/"/','',$data[$f+1]);
228
				} else {
229
					$hostname = gethostbyaddr($leases[$l]['ip']);
230
					if($hostname <> "") {
231
						$leases[$l]['hostname'] = $hostname;
232
					}
233
				}
234
				$f = $f+1;
235
				break;
236
			case "uid":
237
				$f = $f+1;
238
				break;
239
		}
240
		$f++;
241
	}
242
	$l++;
243
	$i++;
244
}
245

    
246
/* remove duplicate items by mac address */
247
if(count($leases) > 0) {
248
	$leases = remove_duplicate($leases,"ip");
249
}
250

    
251
if(count($pools) > 0) {
252
	$pools = remove_duplicate($pools,"name");
253
	asort($pools);
254
}
255

    
256
foreach($config['interfaces'] as $ifname => $ifarr) {
257
	if (is_array($config['dhcpd'][$ifname]) && 
258
		is_array($config['dhcpd'][$ifname]['staticmap'])) {
259
		foreach($config['dhcpd'][$ifname]['staticmap'] as $static) {
260
			$slease = array();
261
			$slease['ip'] = $static['ipaddr'];
262
			$slease['type'] = "static";
263
			$slease['mac'] = $static['mac'];
264
			$slease['start'] = "";
265
			$slease['end'] = "";
266
			$slease['hostname'] = htmlentities($static['hostname']);
267
			$slease['act'] = "static";
268
			$online = exec("/usr/sbin/arp -an |/usr/bin/grep {$slease['mac']}| /usr/bin/wc -l|/usr/bin/awk '{print $1;}'");
269
			if ($online == 1) {
270
				$slease['online'] = 'online';
271
			} else {
272
				$slease['online'] = 'offline';
273
			}
274
			$leases[] = $slease;
275
		}
276
	}
277
}
278

    
279
if ($_GET['order'])
280
	usort($leases, "leasecmp");
281

    
282
/* only print pool status when we have one */
283
if(count($pools) > 0) {
284
?>
285
<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
286
  <tr>
287
    <td class="listhdrr"><?=gettext("Failover Group"); ?></a></td>
288
    <td class="listhdrr"><?=gettext("My State"); ?></a></td>
289
    <td class="listhdrr"><?=gettext("Since"); ?></a></td>
290
    <td class="listhdrr"><?=gettext("Peer State"); ?></a></td>
291
    <td class="listhdrr"><?=gettext("Since"); ?></a></td>
292
  </tr>
293
<?php
294
foreach ($pools as $data) {
295
	echo "<tr>\n";
296
	echo "<td class=\"listlr\">{$fspans}{$data['name']}{$fspane}&nbsp;</td>\n";
297
	echo "<td class=\"listr\">{$fspans}{$data['mystate']}{$fspane}&nbsp;</td>\n";
298
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['mydate']) . "{$fspane}&nbsp;</td>\n";
299
	echo "<td class=\"listr\">{$fspans}{$data['peerstate']}{$fspane}&nbsp;</td>\n";
300
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['peerdate']) . "{$fspane}&nbsp;</td>\n";
301
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
302
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
303
	echo "</tr>\n";
304
}
305

    
306
?>
307
</table>
308

    
309
<?php
310
/* only print pool status when we have one */
311
}
312
?>
313

    
314
<p>
315

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

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

    
399
		/* Only show the button for offline dynamic leases */
400
		if (($data['type'] == "dynamic") && ($data['online'] != "online")) {
401
			echo "<td class=\"list\" valign=\"middle\"><a href=\"status_dhcp_leases.php?deleteip={$data['ip']}&all=" . htmlspecialchars($_GET['all']) . "\">";
402
			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";
403
		}
404
                echo "</tr>\n";
405
	}
406
}
407

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

    
425
<?php include("fend.inc"); ?>
426
</body>
427
</html>
(159-159/226)