mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-13 00:07:26 +00:00
Interfaces/neighbor - implement new neighbor configuration for arp/ndp entries closes https://github.com/opnsense/core/issues/6917
This commit adds a new component linked in Interfaces/Neighbors which offers the ability to manually register static leases and provides application control from other modules such as dhcpd. To minimize the risk, we're reusing the existing interfaces_staticarp_configure() hooks while only adjusting how static arp entries are being attached to the interface (match on addresses assigned when triggering with an interface). Entries registered via dhcp will be visible from the ui as well together with its origin. The previous version didn't cleanup old static entries, this version triggers a cleanup when executed for all interfaces using all earlier modifications processed via the same function (interfaces_neighbors_configure()).
This commit is contained in:
parent
2ae4308a03
commit
1bec000c1e
11
plist
11
plist
@ -385,16 +385,19 @@
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/IPsec/forms/dialogVTI.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/LaggSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/LoopbackSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/NeighborSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VipSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VlanSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VxlanSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/LaggController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/LoopbackController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/NeighborController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/VipController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/VlanController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/VxlanController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogLagg.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogLoopback.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogNeighbor.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogVip.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogVlan.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogVxlan.xml
|
||||
@ -503,6 +506,7 @@
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Core/Config.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Core/ConfigException.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Core/File.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Core/FileObject.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Core/Routing.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Core/Shell.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Core/Singleton.php
|
||||
@ -570,6 +574,7 @@
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/InterfaceField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/JsonKeyValueStoreField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/LegacyLinkField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/MacAddressField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ModelRelationField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/NetworkAliasField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/NetworkField.php
|
||||
@ -675,6 +680,7 @@
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/ACL/ACL.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/FieldTypes/LaggInterfaceField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/FieldTypes/NeighborField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/FieldTypes/VipField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/FieldTypes/VipInterfaceField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/FieldTypes/VipNetworkField.php
|
||||
@ -684,6 +690,9 @@
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Loopback.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Loopback.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Menu/Menu.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Neighbor.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Neighbor.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Neighbor/dhcpd.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Vip.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Vlan.php
|
||||
@ -800,6 +809,7 @@
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/IPsec/vti.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/lagg.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/loopback.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/neighbor.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/vip.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/vlan.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/vxlan.volt
|
||||
@ -1002,6 +1012,7 @@
|
||||
/usr/local/opnsense/scripts/interfaces/ppp-rename.sh
|
||||
/usr/local/opnsense/scripts/interfaces/ppp-uptime.sh
|
||||
/usr/local/opnsense/scripts/interfaces/reconfigure_laggs.php
|
||||
/usr/local/opnsense/scripts/interfaces/reconfigure_neighbors.php
|
||||
/usr/local/opnsense/scripts/interfaces/reconfigure_vips.php
|
||||
/usr/local/opnsense/scripts/interfaces/reconfigure_vlans.php
|
||||
/usr/local/opnsense/scripts/interfaces/rtsold_resolvconf.sh
|
||||
|
||||
@ -3865,17 +3865,67 @@ function interfaces_staticarp_configure($if, $ifconfig_details = null)
|
||||
mwexecf('/usr/sbin/arp -d -i %s -a', [$ifcfg['if']]);
|
||||
}
|
||||
|
||||
if (isset($config['dhcpd'][$if]['staticmap'])) {
|
||||
foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
|
||||
if (!$want && !isset($arpent['arp_table_static_entry'])) {
|
||||
continue;
|
||||
interfaces_neighbors_configure($ifcfg['if'], $ifconfig_details);
|
||||
}
|
||||
|
||||
function interfaces_neighbors_configure($device = null, $ifconfig_details = null)
|
||||
{
|
||||
$subnets = [];
|
||||
|
||||
if (!empty($device)) {
|
||||
if (empty($ifconfig_details) || empty($ifconfig_details[$device])) {
|
||||
/* when called with an interface, require $ifconfig_details being passed */
|
||||
return;
|
||||
}
|
||||
foreach (['ipv4', 'ipv6'] as $proto) {
|
||||
if (!empty($ifconfig_details[$device])) {
|
||||
foreach ($ifconfig_details[$device][$proto] as $item) {
|
||||
$subnets[] = $item['ipaddr'] . '/' . $item['subnetbits'];
|
||||
}
|
||||
}
|
||||
if (!isset($arpent['ipaddr'])) {
|
||||
continue;
|
||||
}
|
||||
mwexecf('/usr/sbin/arp -s %s %s', [$arpent['ipaddr'], $arpent['mac']]);
|
||||
}
|
||||
}
|
||||
|
||||
$current_neightbors = [];
|
||||
foreach ((new \OPNsense\Interfaces\Neighbor())->neighbor->iterateItems() as $key => $node) {
|
||||
$found = empty($if); /* unfiltered when no $if provided */
|
||||
foreach ($subnets as $subnet) {
|
||||
$found = ip_in_subnet((string)$node->ipaddress, $subnet);
|
||||
if ($found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($found) {
|
||||
// IPv4 [arp] or IPv6 [ndp]
|
||||
if (strpos($node->ipaddress, ":") === false) {
|
||||
mwexecf('/usr/sbin/arp -s %s %s', [$node->ipaddress, $node->etheraddr]);
|
||||
} else {
|
||||
mwexecf('/usr/sbin/ndp -s %s %s', [$node->ipaddress, $node->etheraddr]);
|
||||
}
|
||||
}
|
||||
$current_neightbors[] = (string)$node->ipaddress;
|
||||
}
|
||||
|
||||
/* persist accounted addresses, without a cleanup that would be all seen since last cleanup */
|
||||
$fobj = new \OPNsense\Core\FileObject('/tmp/interfaces_neighbors.json', 'a+');
|
||||
$current = $fobj->readJson() ?? [];
|
||||
$fobj->truncate(0)->writeJson(
|
||||
!empty($device) ? array_unique(array_merge($current_neightbors, $current)) : $current_neightbors
|
||||
);
|
||||
unset($fobj);
|
||||
/* only cleanup when applying all interfaces */
|
||||
if (empty($device) && is_array($current)) {
|
||||
foreach ($current as $item) {
|
||||
if (is_string($item) && is_ipaddr($item) && !in_array($item, $current_neightbors)) {
|
||||
if (strpos($item, ":") === false) {
|
||||
mwexecf('/usr/sbin/arp -d %s', [$item]);
|
||||
} else {
|
||||
mwexecf('/usr/sbin/ndp -d %s', [$item]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function get_interfaces_info($include_unlinked = false)
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
<?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\Interfaces\Api;
|
||||
|
||||
use OPNsense\Core\Backend;
|
||||
use OPNsense\Base\ApiMutableModelControllerBase;
|
||||
|
||||
class NeighborSettingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'neighbor';
|
||||
protected static $internalModelClass = 'OPNsense\Interfaces\Neighbor';
|
||||
|
||||
public function searchItemAction()
|
||||
{
|
||||
return $this->searchBase("neighbor", ['etheraddr', 'ipaddress', 'descr', 'origin'], "vxlanid");
|
||||
}
|
||||
|
||||
public function setItemAction($uuid)
|
||||
{
|
||||
return $this->setBase("neighbor", "neighbor", $uuid);
|
||||
}
|
||||
|
||||
public function addItemAction()
|
||||
{
|
||||
return $this->addBase("neighbor", "neighbor");
|
||||
}
|
||||
|
||||
public function getItemAction($uuid = null)
|
||||
{
|
||||
return $this->getBase("neighbor", "neighbor", $uuid);
|
||||
}
|
||||
|
||||
public function delItemAction($uuid)
|
||||
{
|
||||
return $this->delBase("neighbor", $uuid);
|
||||
}
|
||||
|
||||
public function reconfigureAction()
|
||||
{
|
||||
$result = ["status" => "failed"];
|
||||
if ($this->request->isPost()) {
|
||||
$result['status'] = strtolower(trim((new Backend())->configdRun('interface neighbor configure')));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 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\Interfaces;
|
||||
|
||||
class NeighborController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->pick('OPNsense/Interface/neighbor');
|
||||
$this->view->formDialogEdit = $this->getForm("dialogNeighbor");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>neighbor.etheraddr</id>
|
||||
<label>Ether Address</label>
|
||||
<type>text</type>
|
||||
<help>Hardware MAC address of the cllient (format xx:xx:xx:xx:xx:xx)</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>neighbor.ipaddress</id>
|
||||
<label>IP address</label>
|
||||
<type>text</type>
|
||||
<help>IP address to assign to the provided MAC address, which will either end up in the arp (IPv4) or ndp (IPv6) table</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>neighbor.descr</id>
|
||||
<label>Description</label>
|
||||
<type>text</type>
|
||||
<help>You may enter a description here for your reference (not parsed).</help>
|
||||
</field>
|
||||
</form>
|
||||
147
src/opnsense/mvc/app/library/OPNsense/Core/FileObject.php
Normal file
147
src/opnsense/mvc/app/library/OPNsense/Core/FileObject.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?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\Core;
|
||||
|
||||
|
||||
class FileObject
|
||||
{
|
||||
private $fhandle = null;
|
||||
|
||||
/**
|
||||
* File object wrapper
|
||||
* @param string $filename Path to the file where to write the data.
|
||||
* @param string $mode type of access you require to the stream.
|
||||
* @param int $permissions permissions to set, see chmod for usage
|
||||
* @param bool $operation flock operation mode when set
|
||||
*/
|
||||
public function __construct($filename, $mode, $permissions = null, $operation = null)
|
||||
{
|
||||
$this->fhandle = fopen($filename, $mode . 'e'); /* always add close-on-exec flag to prevent fork inherit */
|
||||
|
||||
if ($permissions != null) {
|
||||
@chmod($filename, $permissions);
|
||||
}
|
||||
if ($operation != null) {
|
||||
if (!flock($this->fhandle, $operation)) {
|
||||
fclose($this->fhandle);
|
||||
$this->fhandle = null;
|
||||
throw new Exception('Unable to open file in requested mode.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* close and unlock filehandle
|
||||
*/
|
||||
function __destruct()
|
||||
{
|
||||
if ($this->fhandle) {
|
||||
fclose($this->fhandle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock when locked
|
||||
* @return this
|
||||
*/
|
||||
public function unlock()
|
||||
{
|
||||
flock($this->fhandle, LOCK_UN);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* seek
|
||||
* @param int $offset offset to use
|
||||
* @param int $whence start position
|
||||
* @return this
|
||||
*/
|
||||
public function seek(int $offset, int $whence = SEEK_SET)
|
||||
{
|
||||
fseek($this->fhandle, $whence);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* truncate this file
|
||||
* @param int $whence start position
|
||||
* @return this
|
||||
*/
|
||||
public function truncate(int $size)
|
||||
{
|
||||
ftruncate($this->fhandle, $size);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* read this file
|
||||
* @param int $whence start position
|
||||
* @return payload
|
||||
*/
|
||||
public function read(int $length = -1)
|
||||
{
|
||||
if ($length == -1) {
|
||||
$length = fstat($this->fhandle)['size'];
|
||||
}
|
||||
if ($length === 0) {
|
||||
return null;
|
||||
}
|
||||
return fread($this->fhandle, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* write contents to this file
|
||||
* @param string $data start position
|
||||
* @param int $length length to write
|
||||
* @return this
|
||||
*/
|
||||
public function write(string $data, ?int $length = null)
|
||||
{
|
||||
fwrite($this->fhandle, $data, $length);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* read and parse json content
|
||||
* @return array
|
||||
*/
|
||||
public function readJson()
|
||||
{
|
||||
return json_decode($this->read(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* write array as json data
|
||||
* @return this
|
||||
*/
|
||||
public function writeJson(array $data)
|
||||
{
|
||||
return $this->write(json_encode($data));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
<?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\Base\FieldTypes;
|
||||
|
||||
use OPNsense\Base\Validators\CallbackValidator;
|
||||
|
||||
/**
|
||||
* Class MacAddressField
|
||||
*/
|
||||
class MacAddressField extends TextField
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function defaultValidationMessage()
|
||||
{
|
||||
return gettext('Invalid MAC address.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValidators()
|
||||
{
|
||||
$validators = parent::getValidators();
|
||||
if ($this->internalValue != null) {
|
||||
$validators[] = new CallbackValidator(["callback" => function ($data) {
|
||||
if (empty(filter_var($data, FILTER_VALIDATE_MAC))) {
|
||||
return [$this->getValidationMessage()];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
]);
|
||||
}
|
||||
return $validators;
|
||||
}
|
||||
}
|
||||
@ -103,6 +103,7 @@
|
||||
<Assignments order="900" url="/interfaces_assign.php" cssClass="fa fa-pencil fa-fw"/>
|
||||
<Overview order="910" url="/status_interfaces.php" cssClass="fa fa-tasks fa-fw"/>
|
||||
<Settings order="920" url="/system_advanced_network.php" cssClass="fa fa-cogs fa-fw"/>
|
||||
<Neighbors order="930" url="/ui/interfaces/neighbor" cssClass="fa fa-users fa-fw"/>
|
||||
<Wireless order="940" cssClass="fa fa-wifi fa-fw">
|
||||
<Devices url="/interfaces_wireless.php">
|
||||
<Edit url="/interfaces_wireless_edit.php*" visibility="hidden"/>
|
||||
|
||||
@ -0,0 +1,98 @@
|
||||
<?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\Interfaces\FieldTypes;
|
||||
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use OPNsense\Base\FieldTypes\ArrayField;
|
||||
use OPNsense\Base\FieldTypes\TextField;
|
||||
|
||||
|
||||
class NeighborField extends ArrayField
|
||||
{
|
||||
protected static $internalStaticChildren = [];
|
||||
private static $internalSourcemap = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static function getStaticChildren()
|
||||
{
|
||||
$result = [];
|
||||
foreach (glob(__DIR__ . "/../Neighbor/*.php") as $filename) {
|
||||
$origin = explode('.', basename($filename))[0];
|
||||
$classname = 'OPNsense\\Interfaces\\Neighbor\\' . $origin;
|
||||
try {
|
||||
$class = new ReflectionClass($classname);
|
||||
$obj = $class->newInstance();
|
||||
$dynamic_data = $obj->collect();
|
||||
if (is_array($dynamic_data)) {
|
||||
$seq = 1;
|
||||
foreach ($dynamic_data as $record) {
|
||||
if (is_array($record) && !empty($record['etheraddr']) && !empty($record['ipaddress'])) {
|
||||
$itemKey = sprintf('%s-%s', $origin, $seq);
|
||||
$result[$itemKey] = [
|
||||
'etheraddr' => $record['etheraddr'],
|
||||
'ipaddress' => $record['ipaddress'],
|
||||
'descr' => $record['descr'] ?? ''
|
||||
];
|
||||
self::$internalSourcemap[$itemKey] = $record['source'] ?? $origin;
|
||||
$seq++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Error | \Exception | ReflectionException $e) {
|
||||
syslog(LOG_ERR, sprintf(
|
||||
"Invalid neightbor object %s in %s (%s)", $classname, realpath($filename), $e->getMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function actionPostLoadingEvent()
|
||||
{
|
||||
parent::actionPostLoadingEvent();
|
||||
foreach ($this->iterateItems() as $key => $node) {
|
||||
$type_node = new TextField();
|
||||
$type_node->setInternalIsVirtual();
|
||||
if (isset(self::$internalSourcemap[$key])) {
|
||||
$type_node->setValue(self::$internalSourcemap[$key]);
|
||||
} else {
|
||||
$type_node->setValue('manual');
|
||||
}
|
||||
$node->addChildNode('origin', $type_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/opnsense/mvc/app/models/OPNsense/Interfaces/Neighbor.php
Normal file
35
src/opnsense/mvc/app/models/OPNsense/Interfaces/Neighbor.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?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\Interfaces;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
class Neighbor extends BaseModel
|
||||
{
|
||||
}
|
||||
17
src/opnsense/mvc/app/models/OPNsense/Interfaces/Neighbor.xml
Normal file
17
src/opnsense/mvc/app/models/OPNsense/Interfaces/Neighbor.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<model>
|
||||
<mount>//OPNsense/Interfaces/neighbors</mount>
|
||||
<version>1.0.0</version>
|
||||
<description>Neighbor configuration</description>
|
||||
<items>
|
||||
<neighbor type=".\NeighborField">
|
||||
<etheraddr type="MacAddressField">
|
||||
<Required>Y</Required>
|
||||
</etheraddr>
|
||||
<ipaddress type="NetworkField">
|
||||
<Required>Y</Required>
|
||||
<NetMaskAllowed>N</NetMaskAllowed>
|
||||
</ipaddress>
|
||||
<descr type="TextField"/>
|
||||
</neighbor>
|
||||
</items>
|
||||
</model>
|
||||
@ -0,0 +1,61 @@
|
||||
<?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\Interfaces\Neighbor;
|
||||
|
||||
use OPNsense\Core\Config;
|
||||
|
||||
|
||||
class dhcpd
|
||||
{
|
||||
public function collect()
|
||||
{
|
||||
$result = [];
|
||||
$intfmap = [];
|
||||
$config = Config::getInstance()->object();
|
||||
if ($config->dhcpd->count() > 0) {
|
||||
foreach ($config->dhcpd->children() as $intf => $node) {
|
||||
foreach ($node->children() as $key => $data) {
|
||||
if ($key == 'staticmap') {
|
||||
if (!empty($data->arp_table_static_entry) || !empty($node->staticarp) ) {
|
||||
$result[] = [
|
||||
'etheraddr' => (string)$data->mac,
|
||||
'ipaddress' => (string)$data->ipaddr,
|
||||
'descr' => (string)$data->descr,
|
||||
'source' => sprintf('dhcpd-%s', $intf)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
66
src/opnsense/mvc/app/views/OPNsense/Interface/neighbor.volt
Normal file
66
src/opnsense/mvc/app/views/OPNsense/Interface/neighbor.volt
Normal file
@ -0,0 +1,66 @@
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
$("#grid-neighbor").UIBootgrid(
|
||||
{ search:'/api/interfaces/neighbor_settings/searchItem',
|
||||
get:'/api/interfaces/neighbor_settings/getItem/',
|
||||
set:'/api/interfaces/neighbor_settings/setItem/',
|
||||
add:'/api/interfaces/neighbor_settings/addItem/',
|
||||
del:'/api/interfaces/neighbor_settings/delItem/',
|
||||
options:{
|
||||
formatters: {
|
||||
commands: function (column, row) {
|
||||
if (row.origin == 'manual') {
|
||||
// exclude buttons for internal (dynamic) neighbors
|
||||
return '<button type="button" class="btn btn-xs btn-default command-edit bootgrid-tooltip" data-row-id="' + row.uuid + '"><span class="fa fa-fw fa-pencil"></span></button> ' +
|
||||
'<button type="button" class="btn btn-xs btn-default command-copy bootgrid-tooltip" data-row-id="' + row.uuid + '"><span class="fa fa-fw fa-clone"></span></button>' +
|
||||
'<button type="button" class="btn btn-xs btn-default command-delete bootgrid-tooltip" data-row-id="' + row.uuid + '"><span class="fa fa-fw fa-trash-o"></span></button>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
$("#reconfigureAct").SimpleActionButton();
|
||||
});
|
||||
</script>
|
||||
<div class="tab-content content-box">
|
||||
<table id="grid-neighbor" class="table table-condensed table-hover table-striped" data-editDialog="DialogEdit" data-editAlert="NeighborChangeMessage">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="origin" data-type="string">{{ lang._('Origin') }}</th>
|
||||
<th data-column-id="etheraddr" data-type="string">{{ lang._('Mac') }}</th>
|
||||
<th data-column-id="ipaddress" data-type="string" >{{ lang._('IP address') }}</th>
|
||||
<th data-column-id="descr" data-type="string">{{ lang._('Description') }}</th>
|
||||
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button data-action="add" type="button" class="btn btn-xs btn-primary"><span class="fa fa-fw fa-plus"></span></button>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-fw fa-trash-o"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div class="col-md-12">
|
||||
<div id="NeighborChangeMessage" class="alert alert-info" style="display: none" role="alert">
|
||||
{{ lang._('After changing settings, please remember to apply them with the button below') }}
|
||||
</div>
|
||||
<hr/>
|
||||
<button class="btn btn-primary" id="reconfigureAct"
|
||||
data-endpoint='/api/interfaces/neighbor_settings/reconfigure'
|
||||
data-label="{{ lang._('Apply') }}"
|
||||
data-error-title="{{ lang._('Error reconfiguring neighbors') }}"
|
||||
type="button"
|
||||
></button>
|
||||
<br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEdit,'id':'DialogEdit','label':lang._('Edit Neighbor')])}}
|
||||
34
src/opnsense/scripts/interfaces/reconfigure_neighbors.php
Executable file
34
src/opnsense/scripts/interfaces/reconfigure_neighbors.php
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/local/bin/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.
|
||||
*/
|
||||
|
||||
require_once("config.inc");
|
||||
require_once("interfaces.inc");
|
||||
require_once("util.inc");
|
||||
|
||||
interfaces_neighbors_configure();
|
||||
@ -166,6 +166,11 @@ command: /usr/local/opnsense/scripts/interfaces/reconfigure_vips.php
|
||||
message: Reconfiguring Virtual IPs
|
||||
type: script
|
||||
|
||||
[neighbor.configure]
|
||||
command: /usr/local/opnsense/scripts/interfaces/reconfigure_neighbors.php
|
||||
message: Reconfiguring Neighbors ARP/NDP
|
||||
type: script
|
||||
|
||||
[show.carp]
|
||||
command:/usr/local/opnsense/scripts/interfaces/carp_global_status.php
|
||||
parameters:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user