%PDF- %PDF-
Direktori : /backups/router/usr/local/opnsense/mvc/app/controllers/OPNsense/DHCPv4/Api/ |
Current File : //backups/router/usr/local/opnsense/mvc/app/controllers/OPNsense/DHCPv4/Api/LeasesController.php |
<?php /* * Copyright (C) 2023 Deciso B.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ namespace OPNsense\DHCPv4\Api; use OPNsense\Base\ApiControllerBase; use OPNsense\Core\Backend; use OPNsense\Core\Config; use OPNsense\Firewall\Util; class LeasesController extends ApiControllerBase { public function searchLeaseAction() { $inactive = $this->request->get('inactive'); $selected_interfaces = $this->request->get('selected_interfaces'); $backend = new Backend(); $config = Config::getInstance()->object(); $online = []; $if_devs = []; $if_descrs = []; $ip_ranges = []; $interfaces = []; /* get ARP data to match online clients */ $arp_data = json_decode($backend->configdRun('dhcpd list arp'), true) ?? []; /* get static leases */ $sleases = json_decode($backend->configdRun('dhcpd list static 0'), true) ?? []; /* get dynamic leases, include inactive leases if requested */ $leases = json_decode($backend->configdpRun('dhcpd list leases', [$inactive]), true) ?? []; /* get manufacturer info */ $mac_man = json_decode($backend->configdRun('interface list macdb'), true) ?? []; /* get ifconfig info to match IPs to interfaces */ $ifconfig = json_decode($backend->configdRun('interface list ifconfig'), true) ?? []; /* get all device names and their associated interface names */ foreach ($config->interfaces->children() as $if => $if_props) { $if_devs[$if] = (string)$if_props->if; $if_descrs[$if] = (string)$if_props->descr ?: strtoupper($if); } /* list online IPs and MACs */ if (is_array($arp_data) && isset($arp_data['arp']) && !empty($arp_data['arp']['arp-cache'])) { foreach ($arp_data['arp']['arp-cache'] as $arp_entry) { if (!isset($arp_entry['expired'])) { array_push($online, $arp_entry['mac-address'], $arp_entry['ip-address']); } } } /* gather ip ranges from ifconfig */ foreach ($ifconfig as $if => $data) { if (!empty($data['ipv4'])) { foreach ($data['ipv4'] as $ip) { if (!empty($ip['ipaddr']) && !empty($ip['subnetbits'])) { $ip_ranges[$ip['ipaddr'] . '/' . $ip['subnetbits']] = $if; } } } } /* parse dynamic leases */ foreach ($leases as $idx => $lease) { $leases[$idx]['type'] = 'dynamic'; $leases[$idx]['status'] = 'offline'; $leases[$idx]['descr'] = ''; $leases[$idx]['mac'] = ''; $leases[$idx]['starts'] = ''; $leases[$idx]['ends'] = ''; $leases[$idx]['hostname'] = ''; $leases[$idx]['state'] = $lease['binding'] == 'free' ? 'expired' : $lease['binding']; if (array_key_exists('hardware', $lease)) { $mac = $lease['hardware']['mac-address']; $leases[$idx]['mac'] = $mac; $leases[$idx]['status'] = in_array(strtolower($lease['address']), $online) ? 'online' : 'offline'; unset($leases[$idx]['hardware']); } if (array_key_exists('starts', $lease)) { $leases[$idx]['starts'] = date('Y/m/d H:i:s', $lease['starts']); } if (array_key_exists('ends', $lease)) { $leases[$idx]['ends'] = date('Y/m/d H:i:s', $lease['ends']); } if (array_key_exists('client-hostname', $lease)) { $leases[$idx]['hostname'] = $lease['client-hostname']; } } /* parse static leases */ $statics = []; if ($sleases) { foreach ($sleases["dhcpd"] as $slease) { $static = []; $static['address'] = $slease['ipaddr'] ?? ''; $static['type'] = 'static'; $static['mac'] = $slease['mac'] ?? ''; $static['starts'] = ''; $static['ends'] = ''; $static['hostname'] = $slease['hostname'] ?? ''; $static['descr'] = $slease['descr'] ?? ''; $static['if_descr'] = ''; $static['if'] = $slease['interface'] ?? ''; $static['state'] = 'active'; $static['status'] = in_array(strtolower($static['mac']), $online) ? 'online' : 'offline'; $statics[] = $static; } } /* merge dynamic and static leases */ $leases = array_merge($leases, $statics); foreach ($leases as $idx => $lease) { /* include manufacturer info */ $leases[$idx]['man'] = ''; if ($lease['mac'] != '') { $mac_hi = strtoupper(substr(str_replace(':', '', $lease['mac']), 0, 6)); if (array_key_exists($mac_hi, $mac_man)) { $leases[$idx]['man'] = $mac_man[$mac_hi]; } } /* include interface */ $intf = ''; $intf_descr = ''; if (!empty($lease['if'])) { /* interface already included */ $intf = $lease['if']; $intf_descr = $if_descrs[$intf]; } else { /* interface not known, check range */ foreach ($ip_ranges as $cidr => $if_dev) { if (!empty($lease['address']) && Util::isIPInCIDR($lease['address'], $cidr)) { $intf = array_search($if_dev, $if_devs); $intf_descr = $if_descrs[$intf]; break; } } } $leases[$idx]['if'] = $intf; $leases[$idx]['if_descr'] = $intf_descr; if (!empty($intf_descr) && !array_key_exists($intf, $interfaces)) { $interfaces[$intf] = $intf_descr; } } $response = $this->searchRecordsetBase($leases, null, 'address', function ($key) use ($selected_interfaces) { if (empty($selected_interfaces) || in_array($key['if'], $selected_interfaces)) { return true; } return false; }); /* present relevant interfaces to the view so they can be filtered on */ $response['interfaces'] = $interfaces; return $response; } public function delLeaseAction($ip) { $result = ["result" => "failed"]; if ($this->request->isPost()) { $response = json_decode((new Backend())->configdpRun("dhcpd remove lease", [$ip]), true); if ($response["removed_leases"] != "0") { $result["result"] = "deleted"; } } return $result; } }