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

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

    
243
?>
244

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

    
270
?>
271
</table>
272

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

    
278
<p>
279

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

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

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

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