Project

General

Profile

Download (12.9 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
require("guiconfig.inc");
35

    
36
$pgtitle = "Diagnostics: DHCP leases";
37

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

    
40
if (($_GET['deleteip']) && (is_ipaddr($_GET['deleteip']))) {
41
	/* Stop DHCPD */
42
	killbyname("dhcpd");
43
	
44
	/* Read existing leases */
45
	$leases_contents = explode("\n", file_get_contents($leasesfile));
46
	$newleases_contents = array();
47
	$i=0;
48
	while ($i < count($leases_contents)) {
49
		/* Find the lease(s) we want to delete */
50
		if ($leases_contents[$i] == "lease {$_GET['deleteip']} {") {
51
			/* Skip to the end of the lease declaration */
52
			do {
53
				$i++;
54
			} while ($leases_contents[$i] != "}");
55
		} else {
56
			/* It's a line we want to keep, copy it over. */
57
			$newleases_contents[] = $leases_contents[$i];
58
		}
59
		$i++;
60
	}
61

    
62
	/* Write out the new leases file */
63
	$fd = fopen($leasesfile, 'w');
64
	fwrite($fd, implode("\n", $newleases_contents));
65
	fclose($fd);
66

    
67
	/* Restart DHCP Service */
68
	services_dhcpd_configure();
69
	header("Location: diag_dhcp_leases.php?all={$_GET['all']}");
70
}
71

    
72
include("head.inc");
73

    
74
?>
75

    
76
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
77
<script src="/javascript/sorttable.js"></script>
78
<?php include("fbegin.inc"); ?>
79
<p class="pgtitle"><?=$pgtitle?></p>
80
<?php
81

    
82
function leasecmp($a, $b) {
83
        return strcmp($a[$_GET['order']], $b[$_GET['order']]);
84
}
85

    
86
function adjust_gmt($dt) {
87
        $ts = strtotime($dt . " GMT");
88
        return strftime("%Y/%m/%d %H:%M:%S", $ts);
89
}
90

    
91
function remove_duplicate($array, $field)
92
{
93
  foreach ($array as $sub)
94
   $cmp[] = $sub[$field];
95
  $unique = array_unique(array_reverse($cmp,true));
96
  foreach ($unique as $k => $rien)
97
   $new[] = $array[$k];
98
  return $new;
99
}
100

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

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

    
111
$pools = array();
112
$leases = array();
113
$i = 0;
114
$l = 0;
115
$p = 0;
116

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

    
223
/* remove duplicate items by mac address */
224
if(count($leases) > 0) {
225
	$leases = remove_duplicate($leases,"ip");
226
}
227

    
228
if(count($pools) > 0) {
229
	$pools = remove_duplicate($pools,"name");
230
	asort($pools);
231
}
232

    
233
foreach($config['interfaces'] as $ifname => $ifarr) {
234
	if (is_array($config['dhcpd'][$ifname]['staticmap'])) {
235
		foreach($config['dhcpd'][$ifname]['staticmap'] as $static) {
236
			$slease = array();
237
			$slease['ip'] = $static['ipaddr'];
238
			$slease['type'] = "static";
239
			$slease['mac'] = $static['mac'];
240
			$slease['start'] = "";
241
			$slease['end'] = "";
242
			$slease['hostname'] = htmlentities($static['hostname']);
243
			$slease['act'] = "static";
244
			$online = exec("/usr/sbin/arp -an |/usr/bin/grep {$slease['mac']}| /usr/bin/wc -l|/usr/bin/awk '{print $1;}'");
245
			if ($online == 1) {
246
				$slease['online'] = 'online';
247
			} else {
248
				$slease['online'] = 'offline';
249
			}
250
			$leases[] = $slease;
251
		}
252
	}
253
}
254

    
255
if ($_GET['order'])
256
	usort($leases, "leasecmp");
257

    
258
?>
259

    
260
<?php
261
/* only print pool status when we have one */
262
if(count($pools) > 0) {
263
?>
264
<table class="sortable" id="sortabletable" name="sortabletable" width="100%" border="0" cellpadding="0" cellspacing="0">
265
  <tr>
266
    <td class="listhdrr">Failover Group</a></td>
267
    <td class="listhdrr">My State</a></td>
268
    <td class="listhdrr">Since</a></td>
269
    <td class="listhdrr">Peer State</a></td>
270
    <td class="listhdrr">Since</a></td>
271
  </tr>
272
<?php
273
foreach ($pools as $data) {
274
	echo "<tr>\n";
275
	echo "<td class=\"listlr\">{$fspans}{$data['name']}{$fspane}&nbsp;</td>\n";
276
	echo "<td class=\"listr\">{$fspans}{$data['mystate']}{$fspane}&nbsp;</td>\n";
277
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['mydate']) . "{$fspane}&nbsp;</td>\n";
278
	echo "<td class=\"listr\">{$fspans}{$data['peerstate']}{$fspane}&nbsp;</td>\n";
279
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['peerdate']) . "{$fspane}&nbsp;</td>\n";
280
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
281
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
282
	echo "</tr>\n";
283
}
284

    
285
?>
286
</table>
287

    
288
<?php
289
/* only print pool status when we have one */
290
}
291
?>
292

    
293
<p>
294

    
295
<table class="sortable" id="sortabletable" name="sortabletable" width="100%" border="0" cellpadding="0" cellspacing="0">
296
  <tr>
297
    <td class="listhdrr"><a href="?all=<?=$_GET['all'];?>&order=ip">IP address</a></td>
298
    <td class="listhdrr"><a href="?all=<?=$_GET['all'];?>&order=mac">MAC address</a></td>
299
    <td class="listhdrr"><a href="?all=<?=$_GET['all'];?>&order=hostname">Hostname</a></td>
300
    <td class="listhdrr"><a href="?all=<?=$_GET['all'];?>&order=start">Start</a></td>
301
    <td class="listhdrr"><a href="?all=<?=$_GET['all'];?>&order=end">End</a></td>
302
    <td class="listhdr"><a href="?all=<?=$_GET['all'];?>&order=online">Online</a></td>
303
    <td class="listhdr"><a href="?all=<?=$_GET['all'];?>&order=act">Lease Type</a></td>
304
	</tr>
305
<?php
306
foreach ($leases as $data) {
307
	if (($data['act'] == "active") || ($data['act'] == "static") || ($_GET['all'] == 1)) {
308
		if ($data['act'] != "active" && $data['act'] != "static") {
309
			$fspans = "<span class=\"gray\">";
310
			$fspane = "</span>";
311
		} else {
312
			$fspans = $fspane = "";
313
		}
314
                $lip = ip2long($data['ip']);
315
		if ($data['act'] == "static") {
316
			foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
317
				if(is_array($dhcpifconf['staticmap'])) {
318
					foreach ($dhcpifconf['staticmap'] as $staticent) {
319
						if ($data['ip'] == $staticent['ipaddr']) {
320
							$data['if'] = $dhcpif;
321
							break;
322
						}
323
					}
324
				}
325
				/* exit as soon as we have an interface */
326
				if ($data['if'] != "")
327
					break;
328
			}
329
		} else {
330
                	foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
331
                        	if (($lip >= ip2long($dhcpifconf['range']['from'])) && ($lip <= ip2long($dhcpifconf['range']['to']))) {
332
                                	$data['if'] = $dhcpif;
333
                                	break;
334
                        	}
335
			}
336
                }		
337
		echo "<tr>\n";
338
                echo "<td class=\"listlr\">{$fspans}{$data['ip']}{$fspane}&nbsp;</td>\n";
339
                if ($data['online'] != "online") {
340
                        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";
341
                } else {
342
                	echo "<td class=\"listr\">{$fspans}{$data['mac']}{$fspane}&nbsp;</td>\n";
343
                }
344
                echo "<td class=\"listr\">{$fspans}" . htmlentities($data['hostname']) . "{$fspane}&nbsp;</td>\n";
345
		if ($data['type'] != "static") {
346
			echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['start']) . "{$fspane}&nbsp;</td>\n";
347
			echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['end']) . "{$fspane}&nbsp;</td>\n";
348
		} else {
349
			echo "<td class=\"listr\">{$fspans} n/a {$fspane}&nbsp;</td>\n";
350
			echo "<td class=\"listr\">{$fspans} n/a {$fspane}&nbsp;</td>\n";
351
		}
352
                echo "<td class=\"listr\">{$fspans}{$data['online']}{$fspane}&nbsp;</td>\n";
353
                echo "<td class=\"listr\">{$fspans}{$data['act']}{$fspane}&nbsp;</td>\n";
354
		
355
		if ($data['type'] == "dynamic") {
356
                	echo "<td class=\"list\" valign=\"middle\"><a href=\"services_dhcp_edit.php?if={$data['if']}&mac={$data['mac']}&hostname={$data['hostname']}\">";
357
			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";
358
		} else {
359
                	echo "<td class=\"list\" valign=\"middle\">";
360
			echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus_mo.gif\" width=\"17\" height=\"17\" border=\"0\"></td>\n";
361
		}
362
                echo "<td valign=\"middle\"><a href=\"services_wol_edit.php?if={$data['if']}&mac={$data['mac']}&descr={$data['hostname']}\">";
363
		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";
364

    
365
		/* Only show the button for offline dynamic leases */
366
		if (($data['type'] == "dynamic") && ($data['online'] != "online")) {
367
			echo "<td class=\"list\" valign=\"middle\"><a href=\"diag_dhcp_leases.php?deleteip={$data['ip']}&all={$_GET['all']}\">";
368
			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";
369
		}
370
                echo "</tr>\n";
371
	}
372
}
373

    
374
?>
375
</table>
376
<p>
377
<form action="diag_dhcp_leases.php" method="GET">
378
<input type="hidden" name="order" value="<?=$_GET['order'];?>">
379
<?php if ($_GET['all']): ?>
380
<input type="hidden" name="all" value="0">
381
<input type="submit" class="formbtn" value="Show active and static leases only">
382
<?php else: ?>
383
<input type="hidden" name="all" value="1">
384
<input type="submit" class="formbtn" value="Show all configured leases">
385
<?php endif; ?>
386
</form>
387
<?php if($leases == 0): ?>
388
<p><strong>No leases file found. Is the DHCP server active?</strong></p>
389
<?php endif; ?>
390

    
391
<?php include("fend.inc"); ?>
392
</body>
393
</html>
(9-9/176)