Project

General

Profile

Download (13.1 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	diag_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=diag_dhcp_leases.php*
44
##|-PRIV
45

    
46
require("guiconfig.inc");
47

    
48
$pgtitle = array("Status","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: diag_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 "hardware":
212
				$leases[$l]['mac'] = $data[$f+2];
213
				/* check if it's online and the lease is active */
214
				if (in_array($leases[$l]['ip'], $arpdata)) {
215
					$leases[$l]['online'] = 'online';
216
				} else {
217
					$leases[$l]['online'] = 'offline';
218
				}
219
				$f = $f+2;
220
				break;
221
			case "client-hostname":
222
				if($data[$f+1] <> "") {
223
					$leases[$l]['hostname'] = preg_replace('/"/','',$data[$f+1]);
224
				} else {
225
					$hostname = gethostbyaddr($leases[$l]['ip']);
226
					if($hostname <> "") {
227
						$leases[$l]['hostname'] = $hostname;
228
					}
229
				}
230
				$f = $f+1;
231
				break;
232
			case "uid":
233
				$f = $f+1;
234
				break;
235
		}
236
		$f++;
237
	}
238
	$l++;
239
	$i++;
240
}
241

    
242
/* remove duplicate items by mac address */
243
if(count($leases) > 0) {
244
	$leases = remove_duplicate($leases,"ip");
245
}
246

    
247
if(count($pools) > 0) {
248
	$pools = remove_duplicate($pools,"name");
249
	asort($pools);
250
}
251

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

    
275
if ($_GET['order'])
276
	usort($leases, "leasecmp");
277

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

    
302
?>
303
</table>
304

    
305
<?php
306
/* only print pool status when we have one */
307
}
308
?>
309

    
310
<p>
311

    
312
<table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
313
  <tr>
314
    <td class="listhdrr"><a href="#">IP address</a></td>
315
    <td class="listhdrr"><a href="#">MAC address</a></td>
316
    <td class="listhdrr"><a href="#">Hostname</a></td>
317
    <td class="listhdrr"><a href="#">Start</a></td>
318
    <td class="listhdrr"><a href="#">End</a></td>
319
    <td class="listhdrr"><a href="#">Online</a></td>
320
    <td class="listhdrr"><a href="#">Lease Type</a></td>
321
	</tr>
322
<?php
323
foreach ($leases as $data) {
324
	if (($data['act'] == "active") || ($data['act'] == "static") || ($_GET['all'] == 1)) {
325
		if ($data['act'] != "active" && $data['act'] != "static") {
326
			$fspans = "<span class=\"gray\">";
327
			$fspane = "</span>";
328
		} else {
329
			$fspans = $fspane = "";
330
		}
331
                $lip = ip2long($data['ip']);
332
		if ($data['act'] == "static") {
333
			foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
334
				if(is_array($dhcpifconf['staticmap'])) {
335
					foreach ($dhcpifconf['staticmap'] as $staticent) {
336
						if ($data['ip'] == $staticent['ipaddr']) {
337
							$data['if'] = $dhcpif;
338
							break;
339
						}
340
					}
341
				}
342
				/* exit as soon as we have an interface */
343
				if ($data['if'] != "")
344
					break;
345
			}
346
		} else {
347
                	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {	
348
                        	if (($lip >= ip2long($dhcpifconf['range']['from'])) && ($lip <= ip2long($dhcpifconf['range']['to']))) {
349
                                	$data['if'] = $dhcpif;
350
                                	break;
351
                        	}
352
			}
353
                }		
354
		echo "<tr>\n";
355
                echo "<td class=\"listlr\">{$fspans}{$data['ip']}{$fspane}&nbsp;</td>\n";
356
                if ($data['online'] != "online") {
357
                        echo "<td class=\"listr\">{$fspans}<a href=\"services_wol.php?if={$data['if']}&mac={$data['mac']}\" title=\"send Wake on Lan packet to mac\">{$data['mac']}</a>{$fspane}&nbsp;</td>\n";
358
                } else {
359
                	echo "<td class=\"listr\">{$fspans}{$data['mac']}{$fspane}&nbsp;</td>\n";
360
                }
361
                echo "<td class=\"listr\">{$fspans}"  . htmlentities($data['hostname']) . "{$fspane}&nbsp;</td>\n";
362
				if ($data['type'] != "static") {
363
					echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['start']) . "{$fspane}&nbsp;</td>\n";
364
					echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['end']) . "{$fspane}&nbsp;</td>\n";
365
				} else {
366
					echo "<td class=\"listr\">{$fspans} n/a {$fspane}&nbsp;</td>\n";
367
					echo "<td class=\"listr\">{$fspans} n/a {$fspane}&nbsp;</td>\n";
368
				}
369
                echo "<td class=\"listr\">{$fspans}{$data['online']}{$fspane}&nbsp;</td>\n";
370
                echo "<td class=\"listr\">{$fspans}{$data['act']}{$fspane}&nbsp;</td>\n";
371
		
372
		if ($data['type'] == "dynamic") {
373
			echo "<td valign=\"middle\"><a href=\"services_dhcp_edit.php?if={$data['if']}&mac={$data['mac']}&hostname={$data['hostname']}\">";
374
			echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"add a static mapping for this MAC address\"></a></td>\n";
375
		} else {
376
                	echo "<td class=\"list\" valign=\"middle\">";
377
			echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus_mo.gif\" width=\"17\" height=\"17\" border=\"0\"></td>\n";
378
		}
379

    
380
                echo "<td valign=\"middle\"><a href=\"services_wol_edit.php?if={$data['if']}&mac={$data['mac']}&descr={$data['hostname']}\">";
381
		echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_wol_all.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"add a Wake on Lan mapping for this MAC address\"></a></td>\n";
382

    
383
		/* Only show the button for offline dynamic leases */
384
		if (($data['type'] == "dynamic") && ($data['online'] != "online")) {
385
			echo "<td class=\"list\" valign=\"middle\"><a href=\"diag_dhcp_leases.php?deleteip={$data['ip']}&all={$_GET['all']}\">";
386
			echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"delete this dhcp lease\"></a></td>\n";
387
		}
388
                echo "</tr>\n";
389
	}
390
}
391

    
392
?>
393
</table>
394
<p>
395
<form action="diag_dhcp_leases.php" method="GET">
396
<input type="hidden" name="order" value="<?=$_GET['order'];?>">
397
<?php if ($_GET['all']): ?>
398
<input type="hidden" name="all" value="0">
399
<input type="submit" class="formbtn" value="Show active and static leases only">
400
<?php else: ?>
401
<input type="hidden" name="all" value="1">
402
<input type="submit" class="formbtn" value="Show all configured leases">
403
<?php endif; ?>
404
</form>
405
<?php if($leases == 0): ?>
406
<p><strong>No leases file found. Is the DHCP server active?</strong></p>
407
<?php endif; ?>
408

    
409
<?php include("fend.inc"); ?>
410
</body>
411
</html>
(9-9/218)