.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
##|+PRIV
##|*IDENT=page-status-dhcpleases
##|*NAME=Status: DHCP leases
##|*DESCR=Allow access to the 'Status: DHCP leases' page.
##|*MATCH=status_dhcp_leases.php*
##|-PRIV
require_once("guiconfig.inc");
require_once("config.inc");
$pgtitle = array(gettext("Status"), gettext("DHCP Leases"));
$shortcut_section = "dhcp";
$leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases";
if (($_GET['deleteip']) && (is_ipaddr($_GET['deleteip']))) {
/* Stop DHCPD */
killbyname("dhcpd");
/* Read existing leases */
/* $leases_contents has the lines of the file, including the newline char at the end of each line. */
$leases_contents = file($leasesfile);
$newleases_contents = array();
$i = 0;
while ($i < count($leases_contents)) {
/* Find the lease(s) we want to delete */
if ($leases_contents[$i] == "lease {$_GET['deleteip']} {\n") {
/* Skip to the end of the lease declaration */
do {
$i++;
} while ($leases_contents[$i] != "}\n");
} else {
/* It's a line we want to keep, copy it over. */
$newleases_contents[] = $leases_contents[$i];
}
$i++;
}
/* Write out the new leases file */
$fd = fopen($leasesfile, 'w');
fwrite($fd, implode("\n", $newleases_contents));
fclose($fd);
/* Restart DHCP Service */
services_dhcpd_configure();
header("Location: status_dhcp_leases.php?all={$_GET['all']}");
}
// Load MAC-Manufacturer table
$mac_man = load_mac_manufacturer_table();
include("head.inc");
function leasecmp($a, $b) {
return strcmp($a[$_GET['order']], $b[$_GET['order']]);
}
function adjust_gmt($dt) {
global $config;
$dhcpd = $config['dhcpd'];
foreach ($dhcpd as $dhcpditem) {
$dhcpleaseinlocaltime = $dhcpditem['dhcpleaseinlocaltime'];
if ($dhcpleaseinlocaltime == "yes") {
break;
}
}
if ($dhcpleaseinlocaltime == "yes") {
$ts = strtotime($dt . " GMT");
if ($ts !== false) {
return strftime("%Y/%m/%d %H:%M:%S", $ts);
}
}
/* If we did not need to convert to local time or the conversion failed, just return the input. */
return $dt;
}
function remove_duplicate($array, $field) {
foreach ($array as $sub) {
$cmp[] = $sub[$field];
}
$unique = array_unique(array_reverse($cmp, true));
foreach ($unique as $k => $rien) {
$new[] = $array[$k];
}
return $new;
}
$awk = "/usr/bin/awk";
/* this pattern sticks comments into a single array item */
$cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'";
/* We then split the leases file by } */
$splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'";
/* stuff the leases file in a proper format into a array by line */
exec("/bin/cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content);
$leases_count = count($leases_content);
exec("/usr/sbin/arp -an", $rawdata);
$arpdata_ip = array();
$arpdata_mac = array();
foreach ($rawdata as $line) {
$elements = explode(' ', $line);
if ($elements[3] != "(incomplete)") {
$arpent = array();
$arpdata_ip[] = trim(str_replace(array('(', ')'), '', $elements[1]));
$arpdata_mac[] = strtolower(trim($elements[3]));
}
}
unset($rawdata);
$pools = array();
$leases = array();
$i = 0;
$l = 0;
$p = 0;
// Translate these once so we don't do it over and over in the loops below.
$online_string = gettext("online");
$offline_string = gettext("offline");
$active_string = gettext("active");
$expired_string = gettext("expired");
$reserved_string = gettext("reserved");
$dynamic_string = gettext("dynamic");
$static_string = gettext("static");
// Put everything together again
foreach ($leases_content as $lease) {
/* split the line by space */
$data = explode(" ", $lease);
/* walk the fields */
$f = 0;
$fcount = count($data);
/* with less than 20 fields there is nothing useful */
if ($fcount < 20) {
$i++;
continue;
}
while ($f < $fcount) {
switch ($data[$f]) {
case "failover":
$pools[$p]['name'] = trim($data[$f+2], '"');
$pools[$p]['name'] = "{$pools[$p]['name']} (" . convert_friendly_interface_to_friendly_descr(substr($pools[$p]['name'], 5)) . ")";
$pools[$p]['mystate'] = $data[$f+7];
$pools[$p]['peerstate'] = $data[$f+14];
$pools[$p]['mydate'] = $data[$f+10];
$pools[$p]['mydate'] .= " " . $data[$f+11];
$pools[$p]['peerdate'] = $data[$f+17];
$pools[$p]['peerdate'] .= " " . $data[$f+18];
$p++;
$i++;
continue 3;
case "lease":
$leases[$l]['ip'] = $data[$f+1];
$leases[$l]['type'] = $dynamic_string;
$f = $f+2;
break;
case "starts":
$leases[$l]['start'] = $data[$f+2];
$leases[$l]['start'] .= " " . $data[$f+3];
$f = $f+3;
break;
case "ends":
if ($data[$f+1] == "never") {
// Quote from dhcpd.leases(5) man page:
// If a lease will never expire, date is never instead of an actual date.
$leases[$l]['end'] = gettext("Never");
$f = $f+1;
} else {
$leases[$l]['end'] = $data[$f+2];
$leases[$l]['end'] .= " " . $data[$f+3];
$f = $f+3;
}
break;
case "tstp":
$f = $f+3;
break;
case "tsfp":
$f = $f+3;
break;
case "atsfp":
$f = $f+3;
break;
case "cltt":
$f = $f+3;
break;
case "binding":
switch ($data[$f+2]) {
case "active":
$leases[$l]['act'] = $active_string;
break;
case "free":
$leases[$l]['act'] = $expired_string;
$leases[$l]['online'] = $offline_string;
break;
case "backup":
$leases[$l]['act'] = $reserved_string;
$leases[$l]['online'] = $offline_string;
break;
}
$f = $f+1;
break;
case "next":
/* skip the next binding statement */
$f = $f+3;
break;
case "rewind":
/* skip the rewind binding statement */
$f = $f+3;
break;
case "hardware":
$leases[$l]['mac'] = $data[$f+2];
/* check if it's online and the lease is active */
if (in_array($leases[$l]['ip'], $arpdata_ip)) {
$leases[$l]['online'] = $online_string;
} else {
$leases[$l]['online'] = $offline_string;
}
$f = $f+2;
break;
case "client-hostname":
if ($data[$f+1] <> "") {
$leases[$l]['hostname'] = preg_replace('/"/', '', $data[$f+1]);
} else {
$hostname = gethostbyaddr($leases[$l]['ip']);
if ($hostname <> "") {
$leases[$l]['hostname'] = $hostname;
}
}
$f = $f+1;
break;
case "uid":
$f = $f+1;
break;
}
$f++;
}
$l++;
$i++;
/* slowly chisel away at the source array */
array_shift($leases_content);
}
/* remove the old array */
unset($lease_content);
/* remove duplicate items by mac address */
if (count($leases) > 0) {
$leases = remove_duplicate($leases, "ip");
}
if (count($pools) > 0) {
$pools = remove_duplicate($pools, "name");
asort($pools);
}
foreach ($config['interfaces'] as $ifname => $ifarr) {
if (is_array($config['dhcpd'][$ifname]) &&
is_array($config['dhcpd'][$ifname]['staticmap'])) {
$staticmap_array_index = 0;
foreach ($config['dhcpd'][$ifname]['staticmap'] as $static) {
$slease = array();
$slease['ip'] = $static['ipaddr'];
$slease['type'] = $static_string;
$slease['mac'] = $static['mac'];
$slease['if'] = $ifname;
$slease['start'] = "";
$slease['end'] = "";
$slease['hostname'] = htmlentities($static['hostname']);
$slease['descr'] = htmlentities($static['descr']);
$slease['act'] = $static_string;
$slease['online'] = in_array(strtolower($slease['mac']), $arpdata_mac) ? $online_string : $offline_string;
$slease['staticmap_array_index'] = $staticmap_array_index;
$leases[] = $slease;
$staticmap_array_index++;
}
}
}
if ($_GET['order']) {
usort($leases, "leasecmp");
}
/* only print pool status when we have one */
if (count($pools) > 0) {
?>
=gettext('Pool Status')?>
=gettext("Failover Group")?> |
=gettext("My State")?> |
=gettext("Since")?> |
=gettext("Peer State")?> |
=gettext("Since")?> |
=$data['name']?> |
=$data['mystate']?> |
=adjust_gmt($data['mydate'])?> |
=$data['peerstate']?> |
=adjust_gmt($data['peerdate'])?> |
=gettext('Leases')?>
|
=gettext("IP address")?> |
=gettext("MAC address")?> |
=gettext("Hostname")?> |
=gettext("Description")?> |
=gettext("Start")?> |
=gettext("End")?> |
=gettext("Online")?> |
=gettext("Lease Type")?> |
=gettext("Actions")?> |
$dhcpifconf) {
if (!is_array($dhcpifconf['range'])) {
continue;
}
if (is_inrange_v4($data['ip'], $dhcpifconf['range']['from'], $dhcpifconf['range']['to'])) {
$data['if'] = $dhcpif;
$dlskey = $dhcpif . "-" . $dhcpifconf['range']['from'];
$dhcp_leases_subnet_counter[$dlskey]['dhcpif'] = $dhcpif;
$dhcp_leases_subnet_counter[$dlskey]['from'] = $dhcpifconf['range']['from'];
$dhcp_leases_subnet_counter[$dlskey]['to'] = $dhcpifconf['range']['to'];
$dhcp_leases_subnet_counter[$dlskey]['count'] += 1;
break;
}
// Check if the IP is in the range of any DHCP pools
if (is_array($dhcpifconf['pool'])) {
foreach ($dhcpifconf['pool'] as $dhcppool) {
if (is_array($dhcppool['range'])) {
if (is_inrange_v4($data['ip'], $dhcppool['range']['from'], $dhcppool['range']['to'])) {
$data['if'] = $dhcpif;
$dlskey = $dhcpif . "-" . $dhcppool['range']['from'];
$dhcp_leases_subnet_counter[$dlskey]['dhcpif'] = $dhcpif;
$dhcp_leases_subnet_counter[$dlskey]['from'] = $dhcppool['range']['from'];
$dhcp_leases_subnet_counter[$dlskey]['to'] = $dhcppool['range']['to'];
$dhcp_leases_subnet_counter[$dlskey]['count'] += 1;
break 2;
}
}
}
}
}
}
$mac = $data['mac'];
$mac_hi = strtoupper($mac[0] . $mac[1] . $mac[3] . $mac[4] . $mac[6] . $mac[7]);
?>
|
=$data['ip']?> |
=$mac?>
(=$mac_man[$mac_hi]?>)
|
=$data['hostname']?> |
=$data['descr']?> |
if ($data['type'] != "static"): ?>
=adjust_gmt($data['start'])?> |
=adjust_gmt($data['end'])?> |
else: ?>
=gettext("n/a")?> |
=gettext("n/a")?> |
endif; ?>
=$data['online']?> |
=$data['act']?> |
" href="services_dhcp_edit.php?if==$data['if']?>&mac==$data['mac']?>&hostname==htmlspecialchars($data['hostname'])?>">
" href="services_wol_edit.php?if==$data['if']?>&mac==$data['mac']?>&descr==$data['hostname']?>">
" href="services_wol.php?if==$data['if']?>&mac==$data['mac']?>">
|
=gettext('Leases in Use')?>
=gettext("Interface")?> |
=gettext("Pool Start")?> |
=gettext("Pool End")?> |
=gettext("# of leases in use")?> |
=$iflist[$listcounters['dhcpif']]?> |
=$listcounters['from']?> |
=$listcounters['to']?> |
=$listcounters['count']?> |
=gettext("Show active and static leases only")?>
=gettext("Show all configured leases")?>