Project

General

Profile

Download (12 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
include("head.inc");
46

    
47
?>
48

    
49
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
50
<script src="/javascript/sorttable.js"></script>
51
<?php include("fbegin.inc"); ?>
52
<?php
53

    
54
function leasecmp($a, $b) {
55
        return strcmp($a[$_GET['order']], $b[$_GET['order']]);
56
}
57

    
58
function adjust_gmt($dt) {
59
        $ts = strtotime($dt . " GMT");
60
        return strftime("%Y/%m/%d %H:%M:%S", $ts);
61
}
62

    
63
function remove_duplicate($array, $field)
64
{
65
  foreach ($array as $sub)
66
   $cmp[] = $sub[$field];
67
  $unique = array_unique($cmp);
68
  foreach ($unique as $k => $rien)
69
   $new[] = $array[$k];
70
  return $new;
71
}
72

    
73
$leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases";
74
$awk = "/usr/bin/awk";
75
/* this pattern sticks comments into a single array item */
76
$cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'";
77
/* We then split the leases file by } */
78
$splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'";
79

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

    
84
exec("/usr/sbin/arp -an", $rawdata);
85
$arpdata = array();
86
foreach ($rawdata as $line) {
87
	$elements = explode(' ',$line);
88
	if ($elements[3] != "(incomplete)") {
89
		$arpent = array();
90
		$arpent['ip'] = trim(str_replace(array('(',')'),'',$elements[1]));
91
		// $arpent['mac'] = trim($elements[3]);
92
		// $arpent['interface'] = trim($elements[5]);
93
	$arpdata[] = $arpent['ip'];
94
	}
95
}
96

    
97
$pools = array();
98
$leases = array();
99
$i = 0;
100
$l = 0;
101
$p = 0;
102

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

    
206
/* remove duplicate items by mac address */
207
if(count($leases) > 0) {
208
	$leases = remove_duplicate($leases,"ip");
209
}
210

    
211
if(count($pools) > 0) {
212
	$pools = remove_duplicate($pools,"name");
213
	asort($pools);
214
}
215

    
216
foreach($config['interfaces'] as $ifname => $ifarr) {
217
	if (is_array($config['dhcpd'][$ifname]['staticmap'])) {
218
		foreach($config['dhcpd'][$ifname]['staticmap'] as $static) {
219
			$slease = array();
220
			$slease['ip'] = $static['ipaddr'];
221
			$slease['type'] = "static";
222
			$slease['mac'] = $static['mac'];
223
			$slease['start'] = gmdate("M d Y H:i:s", time());
224
			$slease['end'] = gmdate("M d Y H:i:s", time());
225
			$slease['end'] = gmdate("M d Y H:i:s", strtotime('+5 minutes'));
226
			$slease['hostname'] = htmlentities($static['hostname']);
227
			$slease['act'] = "static";
228
			$online = exec("/usr/sbin/arp -an |/usr/bin/grep {$slease['mac']}| /usr/bin/wc -l|/usr/bin/awk '{print $1;}'");
229
			if ($online == 1) {
230
				$slease['online'] = 'online';
231
			} else {
232
				$slease['online'] = 'offline';
233
			}
234
			$leases[] = $slease;
235
		}
236
	}
237
}
238

    
239
if ($_GET['order'])
240
	usort($leases, "leasecmp");
241

    
242
?>
243

    
244
<?php
245
/* only print pool status when we have one */
246
if(count($pools) > 0) {
247
?>
248
<table class="sortable" id="sortabletable" name="sortabletable" width="100%" border="0" cellpadding="0" cellspacing="0">
249
  <tr>
250
    <td class="listhdrr">Failover Group</a></td>
251
    <td class="listhdrr">My State</a></td>
252
    <td class="listhdrr">Since</a></td>
253
    <td class="listhdrr">Peer State</a></td>
254
    <td class="listhdrr">Since</a></td>
255
  </tr>
256
<?php
257
foreach ($pools as $data) {
258
	echo "<tr>\n";
259
	echo "<td class=\"listlr\">{$fspans}{$data['name']}{$fspane}&nbsp;</td>\n";
260
	echo "<td class=\"listr\">{$fspans}{$data['mystate']}{$fspane}&nbsp;</td>\n";
261
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['mydate']) . "{$fspane}&nbsp;</td>\n";
262
	echo "<td class=\"listr\">{$fspans}{$data['peerstate']}{$fspane}&nbsp;</td>\n";
263
	echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['peerdate']) . "{$fspane}&nbsp;</td>\n";
264
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
265
	echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
266
	echo "</tr>\n";
267
}
268

    
269
?>
270
</table>
271

    
272
<?php
273
/* only print pool status when we have one */
274
}
275
?>
276

    
277
<p>
278

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

    
342
                echo "<td valign=\"middle\"><a href=\"services_wol_edit.php?if={$data['if']}&mac={$data['mac']}&descr={$data['hostname']}\">";
343
		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";
344
                echo "</tr>\n";
345
	}
346
}
347

    
348
?>
349
</table>
350
<p>
351
<form action="diag_dhcp_leases.php" method="GET">
352
<input type="hidden" name="order" value="<?=$_GET['order'];?>">
353
<?php if ($_GET['all']): ?>
354
<input type="hidden" name="all" value="0">
355
<input type="submit" class="formbtn" value="Show active and static leases only">
356
<?php else: ?>
357
<input type="hidden" name="all" value="1">
358
<input type="submit" class="formbtn" value="Show all configured leases">
359
<?php endif; ?>
360
</form>
361
<?php if($leases == 0): ?>
362
<p><strong>No leases file found. Is the DHCP server active?</strong></p>
363
<?php endif; ?>
364

    
365
<?php include("fend.inc"); ?>
366
</body>
367
</html>
(8-8/205)