Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

univnautes / usr / local / www / status_dhcp_leases.php @ 3c4cddc7

History | View | Annotate | Download (14.9 KB)

1
<?php
2
/* $Id$ */
3
/*
4
        status_dhcp_leases.php
5
        Copyright (C) 2004-2009 Scott Ullrich
6
        All rights reserved.
7

8
        originally 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=status_dhcp_leases.php*
44
##|-PRIV
45

    
46
require("guiconfig.inc");
47
require_once("config.inc");
48

    
49
$pgtitle = array(gettext("Status"),gettext("DHCP leases"));
50
$shortcut_section = "dhcp";
51

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

    
54
if (($_GET['deleteip']) && (is_ipaddr($_GET['deleteip']))) {
55
        /* Stop DHCPD */
56
        killbyname("dhcpd");
57

    
58
        /* Read existing leases */
59
        /* $leases_contents has the lines of the file, including the newline char at the end of each line. */
60
        $leases_contents = file($leasesfile);
61
        $newleases_contents = array();
62
        $i=0;
63
        while ($i < count($leases_contents)) {
64
                /* Find the lease(s) we want to delete */
65
                if ($leases_contents[$i] == "lease {$_GET['deleteip']} {\n") {
66
                        /* Skip to the end of the lease declaration */
67
                        do {
68
                                $i++;
69
                        } while ($leases_contents[$i] != "}\n");
70
                } else {
71
                        /* It's a line we want to keep, copy it over. */
72
                        $newleases_contents[] = $leases_contents[$i];
73
                }
74
                $i++;
75
        }
76

    
77
        /* Write out the new leases file */
78
        $fd = fopen($leasesfile, 'w');
79
        fwrite($fd, implode("\n", $newleases_contents));
80
        fclose($fd);
81

    
82
        /* Restart DHCP Service */
83
        services_dhcpd_configure();
84
        header("Location: status_dhcp_leases.php?all={$_GET['all']}");
85
}
86

    
87
include("head.inc");
88

    
89
?>
90

    
91
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
92
<?php include("fbegin.inc"); ?>
93
<?php
94

    
95
function leasecmp($a, $b) {
96
        return strcmp($a[$_GET['order']], $b[$_GET['order']]);
97
}
98

    
99
function adjust_gmt($dt) {
100
        global $config; 
101
        $dhcpd = $config['dhcpd'];
102
        foreach ($dhcpd as $dhcpditem) {
103
                $dhcpleaseinlocaltime = $dhcpditem['dhcpleaseinlocaltime'];
104
                if ($dhcpleaseinlocaltime == "yes") 
105
                        break;
106
        }
107
        if ($dhcpleaseinlocaltime == "yes") {
108
                $ts = strtotime($dt . " GMT");
109
                return strftime("%Y/%m/%d %I:%M:%S%p", $ts);
110
        } else
111
                return $dt;
112
}
113

    
114
function remove_duplicate($array, $field)
115
{
116
  foreach ($array as $sub)
117
   $cmp[] = $sub[$field];
118
  $unique = array_unique(array_reverse($cmp,true));
119
  foreach ($unique as $k => $rien)
120
   $new[] = $array[$k];
121
  return $new;
122
}
123

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

    
130
/* stuff the leases file in a proper format into a array by line */
131
exec("/bin/cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content);
132
$leases_count = count($leases_content);
133
exec("/usr/sbin/arp -an", $rawdata);
134
$arpdata_ip = array();
135
$arpdata_mac = array();
136
foreach ($rawdata as $line) {
137
        $elements = explode(' ',$line);
138
        if ($elements[3] != "(incomplete)") {
139
                $arpent = array();
140
                $arpdata_ip[] = trim(str_replace(array('(',')'),'',$elements[1]));
141
                $arpdata_mac[] = strtolower(trim($elements[3]));
142
        }
143
}
144
unset($rawdata);
145
$pools = array();
146
$leases = array();
147
$i = 0;
148
$l = 0;
149
$p = 0;
150

    
151
// Put everything together again
152
foreach($leases_content as $lease) {
153
        /* split the line by space */
154
        $data = explode(" ", $lease);
155
        /* walk the fields */
156
        $f = 0;
157
        $fcount = count($data);
158
        /* with less then 20 fields there is nothing useful */
159
        if($fcount < 20) {
160
                $i++;
161
                continue;
162
        }
163
        while($f < $fcount) {
164
                switch($data[$f]) {
165
                        case "failover":
166
                                $pools[$p]['name'] = trim($data[$f+2], '"');
167
                                $pools[$p]['name'] = "{$pools[$p]['name']} (" . convert_friendly_interface_to_friendly_descr(substr($pools[$p]['name'], 5)) . ")";
168
                                $pools[$p]['mystate'] = $data[$f+7];
169
                                $pools[$p]['peerstate'] = $data[$f+14];
170
                                $pools[$p]['mydate'] = $data[$f+10];
171
                                $pools[$p]['mydate'] .= " " . $data[$f+11];
172
                                $pools[$p]['peerdate'] = $data[$f+17];
173
                                $pools[$p]['peerdate'] .= " " . $data[$f+18];
174
                                $p++;
175
                                $i++;
176
                                continue 3;
177
                        case "lease":
178
                                $leases[$l]['ip'] = $data[$f+1];
179
                                $leases[$l]['type'] = "dynamic";
180
                                $f = $f+2;
181
                                break;
182
                        case "starts":
183
                                $leases[$l]['start'] = $data[$f+2];
184
                                $leases[$l]['start'] .= " " . $data[$f+3];
185
                                $f = $f+3;
186
                                break;
187
                        case "ends":
188
                                $leases[$l]['end'] = $data[$f+2];
189
                                $leases[$l]['end'] .= " " . $data[$f+3];
190
                                $f = $f+3;
191
                                break;
192
                        case "tstp":
193
                                $f = $f+3;
194
                                break;
195
                        case "tsfp":
196
                                $f = $f+3;
197
                                break;
198
                        case "atsfp":
199
                                $f = $f+3;
200
                                break;
201
                        case "cltt":
202
                                $f = $f+3;
203
                                break;
204
                        case "binding":
205
                                switch($data[$f+2]) {
206
                                        case "active":
207
                                                $leases[$l]['act'] = "active";
208
                                                break;
209
                                        case "free":
210
                                                $leases[$l]['act'] = "expired";
211
                                                $leases[$l]['online'] = "offline";
212
                                                break;
213
                                        case "backup":
214
                                                $leases[$l]['act'] = "reserved";
215
                                                $leases[$l]['online'] = "offline";
216
                                                break;
217
                                }
218
                                $f = $f+1;
219
                                break;
220
                        case "next":
221
                                /* skip the next binding statement */
222
                                $f = $f+3;
223
                                break;
224
                        case "rewind":
225
                                /* skip the rewind binding statement */
226
                                $f = $f+3;
227
                                break;
228
                        case "hardware":
229
                                $leases[$l]['mac'] = $data[$f+2];
230
                                /* check if it's online and the lease is active */
231
                                if (in_array($leases[$l]['ip'], $arpdata_ip)) {
232
                                        $leases[$l]['online'] = 'online';
233
                                } else {
234
                                        $leases[$l]['online'] = 'offline';
235
                                }
236
                                $f = $f+2;
237
                                break;
238
                        case "client-hostname":
239
                                if($data[$f+1] <> "") {
240
                                        $leases[$l]['hostname'] = preg_replace('/"/','',$data[$f+1]);
241
                                } else {
242
                                        $hostname = gethostbyaddr($leases[$l]['ip']);
243
                                        if($hostname <> "") {
244
                                                $leases[$l]['hostname'] = $hostname;
245
                                        }
246
                                }
247
                                $f = $f+1;
248
                                break;
249
                        case "uid":
250
                                $f = $f+1;
251
                                break;
252
                }
253
                $f++;
254
        }
255
        $l++;
256
        $i++;
257
        /* slowly chisel away at the source array */
258
        array_shift($leases_content);
259
}
260
/* remove the old array */
261
unset($lease_content);
262

    
263
/* remove duplicate items by mac address */
264
if(count($leases) > 0) {
265
        $leases = remove_duplicate($leases,"ip");
266
}
267

    
268
if(count($pools) > 0) {
269
        $pools = remove_duplicate($pools,"name");
270
        asort($pools);
271
}
272

    
273
foreach($config['interfaces'] as $ifname => $ifarr) {
274
        if (is_array($config['dhcpd'][$ifname]) && 
275
                is_array($config['dhcpd'][$ifname]['staticmap'])) {
276
                foreach($config['dhcpd'][$ifname]['staticmap'] as $static) {
277
                        $slease = array();
278
                        $slease['ip'] = $static['ipaddr'];
279
                        $slease['type'] = "static";
280
                        $slease['mac'] = $static['mac'];
281
                        $slease['start'] = "";
282
                        $slease['end'] = "";
283
                        $slease['hostname'] = htmlentities($static['hostname']);
284
                        $slease['act'] = "static";
285
                        $slease['online'] = in_array(strtolower($slease['mac']), $arpdata_mac) ? 'online' : 'offline';
286
                        $leases[] = $slease;
287
                }
288
        }
289
}
290

    
291
if ($_GET['order'])
292
        usort($leases, "leasecmp");
293

    
294
/* only print pool status when we have one */
295
if(count($pools) > 0) {
296
?>
297
<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0" summary="dhcp leases">
298
  <tr>
299
    <td class="listhdrr"><?=gettext("Failover Group"); ?></a></td>
300
    <td class="listhdrr"><?=gettext("My State"); ?></a></td>
301
    <td class="listhdrr"><?=gettext("Since"); ?></a></td>
302
    <td class="listhdrr"><?=gettext("Peer State"); ?></a></td>
303
    <td class="listhdrr"><?=gettext("Since"); ?></a></td>
304
  </tr>
305
<?php
306
foreach ($pools as $data) {
307
        echo "<tr>\n";
308
        echo "<td class=\"listlr\">{$fspans}{$data['name']}{$fspane}</td>\n";
309
        echo "<td class=\"listr\">{$fspans}{$data['mystate']}{$fspane}</td>\n";
310
        echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['mydate']) . "{$fspane}</td>\n";
311
        echo "<td class=\"listr\">{$fspans}{$data['peerstate']}{$fspane}</td>\n";
312
        echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['peerdate']) . "{$fspane}</td>\n";
313
        echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
314
        echo "<td class=\"list\" valign=\"middle\" width=\"17\">&nbsp;</td>\n";
315
        echo "</tr>\n";
316
}
317

    
318
?>
319
</table>
320

    
321
<?php
322
/* only print pool status when we have one */
323
}
324
?>
325

    
326
<br/>
327

    
328
<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0" summary="dhcp leases">
329
  <tr>
330
    <td class="listhdrr"><a href="#"><?=gettext("IP address"); ?></a></td>
331
    <td class="listhdrr"><a href="#"><?=gettext("MAC address"); ?></a></td>
332
    <td class="listhdrr"><a href="#"><?=gettext("Hostname"); ?></a></td>
333
    <td class="listhdrr"><a href="#"><?=gettext("Start"); ?></a></td>
334
    <td class="listhdrr"><a href="#"><?=gettext("End"); ?></a></td>
335
    <td class="listhdrr"><a href="#"><?=gettext("Online"); ?></a></td>
336
    <td class="listhdrr"><a href="#"><?=gettext("Lease Type"); ?></a></td>
337
        </tr>
338
<?php
339
// Load MAC-Manufacturer table
340
$mac_man = load_mac_manufacturer_table();
341
foreach ($leases as $data) {
342
        if (($data['act'] == "active") || ($data['act'] == "static") || ($_GET['all'] == 1)) {
343
                if ($data['act'] != "active" && $data['act'] != "static") {
344
                        $fspans = "<span class=\"gray\">";
345
                        $fspane = "&nbsp;</span>";
346
                } else {
347
                        $fspans = "";
348
                        $fspane = "&nbsp;";
349
                }
350
                $lip = ip2ulong($data['ip']);
351
                if ($data['act'] == "static") {
352
                        foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
353
                                if(is_array($dhcpifconf['staticmap'])) {
354
                                        foreach ($dhcpifconf['staticmap'] as $staticent) {
355
                                                if ($data['ip'] == $staticent['ipaddr']) {
356
                                                        $data['if'] = $dhcpif;
357
                                                        break;
358
                                                }
359
                                        }
360
                                }
361
                                /* exit as soon as we have an interface */
362
                                if ($data['if'] != "")
363
                                        break;
364
                        }
365
                } else {
366
                        foreach ($config['dhcpd'] as $dhcpif => $dhcpifconf) {
367
                                if (!is_array($dhcpifconf['range']))
368
                                        continue;
369
                                if (($lip >= ip2ulong($dhcpifconf['range']['from'])) && ($lip <= ip2ulong($dhcpifconf['range']['to']))) {
370
                                        $data['if'] = $dhcpif;
371
                                        break;
372
                                }
373
                        }
374
                }                
375
                echo "<tr>\n";
376
                echo "<td class=\"listlr\">{$fspans}{$data['ip']}{$fspane}</td>\n";
377
                $mac=$data['mac']; 
378
                $mac_hi = strtoupper($mac[0] . $mac[1] . $mac[3] . $mac[4] . $mac[6] . $mac[7]);
379
                if ($data['online'] != "online") {
380
                        if(isset($mac_man[$mac_hi])){ // Manufacturer for this MAC is defined
381
                                echo "<td class=\"listr\">{$fspans}<a href=\"services_wol.php?if={$data['if']}&amp;mac=$mac\" title=\"" . gettext("$mac - send Wake on LAN packet to this MAC address") ."\">{$mac}</a><br /><font size=\"-2\"><i>{$mac_man[$mac_hi]}</i></font>{$fspane}</td>\n";
382
                        }else{        
383
                                echo "<td class=\"listr\">{$fspans}<a href=\"services_wol.php?if={$data['if']}&amp;mac={$data['mac']}\" title=\"" . gettext("send Wake on LAN packet to this MAC address") ."\">{$data['mac']}</a>{$fspane}</td>\n";
384
                        }
385
                }else{
386
                        if(isset($mac_man[$mac_hi])){ // Manufacturer for this MAC is defined
387
                                echo "<td class=\"listr\">{$fspans}{$mac}<br /><font size=\"-2\"><i>{$mac_man[$mac_hi]}</i></font>{$fspane}</td>\n";
388
                        }else{
389
                                echo "<td class=\"listr\">{$fspans}{$data['mac']}{$fspane}</td>\n";
390
                        }
391
                }
392
                echo "<td class=\"listr\">{$fspans}"  . htmlentities($data['hostname']) . "{$fspane}</td>\n";
393
                                if ($data['type'] != "static") {
394
                                        echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['start']) . "{$fspane}</td>\n";
395
                                        echo "<td class=\"listr\">{$fspans}" . adjust_gmt($data['end']) . "{$fspane}</td>\n";
396
                                } else {
397
                                        echo "<td class=\"listr\">{$fspans} n/a {$fspane}</td>\n";
398
                                        echo "<td class=\"listr\">{$fspans} n/a {$fspane}</td>\n";
399
                                }
400
                echo "<td class=\"listr\">{$fspans}{$data['online']}{$fspane}</td>\n";
401
                echo "<td class=\"listr\">{$fspans}{$data['act']}{$fspane}</td>\n";
402
                echo "<td valign=\"middle\">&nbsp;";
403
                if ($data['type'] == "dynamic") {
404
                        echo "<a href=\"services_dhcp_edit.php?if={$data['if']}&amp;mac={$data['mac']}&amp;hostname={$data['hostname']}\">";
405
                        echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("add a static mapping for this MAC address") ."\" alt=\"add\" /></a>&nbsp;\n";
406
                } else {
407
                        echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_plus_mo.gif\" width=\"17\" height=\"17\" border=\"0\" alt=\"add\" />&nbsp;\n";
408
                }
409

    
410
                echo "<a href=\"services_wol_edit.php?if={$data['if']}&amp;mac={$data['mac']}&amp;descr={$data['hostname']}\">";
411
                echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_wol_all.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("add a Wake on LAN mapping for this MAC address") ."\" alt=\"add\" /></a>&nbsp;\n";
412

    
413
                /* Only show the button for offline dynamic leases */
414
                if (($data['type'] == "dynamic") && ($data['online'] != "online")) {
415
                        echo "<a href=\"status_dhcp_leases.php?deleteip={$data['ip']}&amp;all=" . htmlspecialchars($_GET['all']) . "\">";
416
                        echo "<img src=\"/themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"17\" height=\"17\" border=\"0\" title=\"" . gettext("delete this DHCP lease") . "\" alt=\"delete\" /></a>&nbsp;\n";
417
                }
418
                echo "</td></tr>\n";
419
        }
420
}
421

    
422
?>
423
</table>
424
<br/>
425
<form action="status_dhcp_leases.php" method="get">
426
<input type="hidden" name="order" value="<?=htmlspecialchars($_GET['order']);?>" />
427
<?php if ($_GET['all']): ?>
428
<input type="hidden" name="all" value="0" />
429
<input type="submit" class="formbtn" value="<?=gettext("Show active and static leases only"); ?>" />
430
<?php else: ?>
431
<input type="hidden" name="all" value="1" />
432
<input type="submit" class="formbtn" value="<?=gettext("Show all configured leases"); ?>" />
433
<?php endif; ?>
434
</form>
435
<?php if($leases == 0): ?>
436
<p><strong><?=gettext("No leases file found. Is the DHCP server active"); ?>?</strong></p>
437
<?php endif; ?>
438

    
439
<?php include("fend.inc"); ?>
440
</body>
441
</html>