Project

General

Profile

Download (13 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	diag_dhcp_leases.php
5
	Copyright (C) 2004 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
##|+PRIV
35
##|*IDENT=page-status-dhcpleases
36
##|*NAME=Status: DHCP leases page
37
##|*DESCR=Allow access to the 'Status: DHCP leases' page.
38
##|*MATCH=diag_dhcp_leases.php*
39
##|-PRIV
40

    
41

    
42
require("guiconfig.inc");
43

    
44
$pgtitle = array("Status","DHCP leases");
45

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

    
48
if (($_GET['deleteip']) && (is_ipaddr($_GET['deleteip']))) {
49
	/* Stop DHCPD */
50
	killbyname("dhcpd");
51

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

    
70
	/* Write out the new leases file */
71
	$fd = fopen($leasesfile, 'w');
72
	fwrite($fd, implode("\n", $newleases_contents));
73
	fclose($fd);
74

    
75
	/* Restart DHCP Service */
76
	services_dhcpd_configure();
77
	header("Location: diag_dhcp_leases.php?all={$_GET['all']}");
78
}
79

    
80
include("head.inc");
81

    
82
?>
83

    
84
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
85
<?php include("fbegin.inc"); ?>
86
<?php
87

    
88
function leasecmp($a, $b) {
89
        return strcmp($a[$_GET['order']], $b[$_GET['order']]);
90
}
91

    
92
function adjust_gmt($dt) {
93
        $ts = strtotime($dt . " GMT");
94
        return strftime("%Y/%m/%d %H:%M:%S", $ts);
95
}
96

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

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

    
113
/* stuff the leases file in a proper format into a array by line */
114
exec("cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content);
115
$leases_count = count($leases_content);
116

    
117
exec("/usr/sbin/arp -an", $rawdata);
118
$arpdata = array();
119
foreach ($rawdata as $line) {
120
	$elements = explode(' ',$line);
121
	if ($elements[3] != "(incomplete)") {
122
		$arpent = array();
123
		$arpent['ip'] = trim(str_replace(array('(',')'),'',$elements[1]));
124
		// $arpent['mac'] = trim($elements[3]);
125
		// $arpent['interface'] = trim($elements[5]);
126
	$arpdata[] = $arpent['ip'];
127
	}
128
}
129

    
130
$pools = array();
131
$leases = array();
132
$i = 0;
133
$l = 0;
134
$p = 0;
135

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

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

    
244
if(count($pools) > 0) {
245
	$pools = remove_duplicate($pools,"name");
246
	asort($pools);
247
}
248

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

    
272
if ($_GET['order'])
273
	usort($leases, "leasecmp");
274

    
275
?>
276

    
277
<?php
278
/* only print pool status when we have one */
279
if(count($pools) > 0) {
280
?>
281
<table class="tabcont" 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>
(7-7/217)