Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions net/frr/src/etc/inc/plugins.inc.d/frr.inc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ function frr_carp_enabled()
(string)$model->enablecarp == '1';
}

function frr_configure()
{
return [
'frr_sync' => ['frr_configure_do'],
];
}

function frr_configure_do($verbose = false)
{
$model = new \OPNsense\Quagga\General();
if (!$model->manual_config->isEmpty()) {
return;
}
(new \OPNsense\Core\Backend())->configdpRun('template reload', ['OPNsense/Quagga']);
}

function frr_firewall($fw)
{
global $config;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
class ServiceController extends ApiMutableServiceControllerBase
{
protected static $internalServiceClass = '\OPNsense\Quagga\General';
protected static $internalServiceTemplate = 'OPNsense/Quagga';
// We intentionally only reload this template to allow manual_config for the templates
protected static $internalServiceTemplate = 'OPNsense/Quagga/rc_conf_d';
protected static $internalServiceEnabled = 'enabled';
protected static $internalServiceName = 'quagga';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@
<type>checkbox</type>
<help>This will activate the routing service. Without enabling it globally, none of the individual services will run.</help>
</field>
<field>
<id>general.daemons</id>
<label>Enabled daemons</label>
<type>select_multiple</type>
<help>Shows which FRR daemons are enabled by the individual daemon pages. This remains relevant when manual configuration is enabled because the rc.d service wrapper is still generated.</help>
</field>
<field>
<id>general.manual_config</id>
<label>Manual config</label>
<type>checkbox</type>
<help>Disable configuration file generation and manage the file (/usr/local/etc/frr/frr.conf) manually.</help>
</field>
<field>
<id>general.profile</id>
<label>Profile</label>
<type>dropdown</type>
<advanced>true</advanced>
<style>manual_config_hide selectpicker</style>
<help>Control FRR’s default profile: traditional reflects defaults adhering mostly to IETF standards or common practices in wide-area internet routing. datacenter reflects a single administrative domain with intradomain links using aggressive timers.</help>
</field>
<field>
Expand All @@ -28,12 +40,14 @@
<id>general.enablesyslog</id>
<label>Enable logging</label>
<type>checkbox</type>
<style>manual_config_hide</style>
<help>Sends logs to the OPNsense integrated syslog-ng service.</help>
</field>
<field>
<id>general.sysloglevel</id>
<label>Log Level</label>
<type>dropdown</type>
<style>manual_config_hide selectpicker</style>
<help>This is the detail level of the log. A higher level means more data is logged.</help>
</field>
<field>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/*
* Copyright (C) 2026 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\Quagga\FieldTypes;

use OPNsense\Base\FieldTypes\OptionField;
use OPNsense\Core\Config;

class EnableDaemonField extends OptionField
{
public const CONFIG_SECTIONS = ['bfd', 'bgp', 'ospf', 'ospf6', 'rip', 'static'];
protected function actionPostLoadingEvent()
{
$quagga = Config::getInstance()->object()->OPNsense->quagga ?? null;
$enabled = [];

foreach (self::CONFIG_SECTIONS as $section) {
if (!empty($quagga?->{$section}?->enabled)) {
$enabled[] = $section;
}
}

$this->setValue(implode(',', $enabled));

return parent::actionPostLoadingEvent();
}
}
68 changes: 42 additions & 26 deletions net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/General.php
Original file line number Diff line number Diff line change
@@ -1,35 +1,51 @@
<?php

namespace OPNsense\Quagga;

use OPNsense\Base\BaseModel;

/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
* Copyright (C) 2026 Deciso B.V.
* Copyright (C) 2017 Fabian Franz
* 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 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.
*/

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.
namespace OPNsense\Quagga;

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.
*/
use OPNsense\Base\BaseModel;
use OPNsense\Core\Config;
use OPNsense\Quagga\FieldTypes\EnableDaemonField;

class General extends BaseModel
{
public function serializeToConfig($validateFullModel = false, $disable_validation = false)
{
$result = parent::serializeToConfig($validateFullModel, $disable_validation);
$config = Config::getInstance()->object();
$enabledSections = $this->daemons->getValues();

foreach (EnableDaemonField::CONFIG_SECTIONS as $section) {
$config->OPNsense->quagga->{$section}->enabled =
in_array($section, $enabledSections, true) ? '1' : '0';
}

return $result;
}
}
17 changes: 16 additions & 1 deletion net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/General.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
<model>
<mount>//OPNsense/quagga/general</mount>
<description>Quagga Routing configuration</description>
<version>1.0.3</version>
<version>1.0.4</version>
<items>
<enabled type="BooleanField">
<Default>0</Default>
<Required>Y</Required>
</enabled>
<daemons type=".\EnableDaemonField" volatile="true">
<Multiple>Y</Multiple>
<OptionValues>
<bfd/>
<bgp/>
<ospf/>
<ospf6/>
<rip/>
<static/>
</OptionValues>
</daemons>
<manual_config type="BooleanField">
<Default>0</Default>
<Required>Y</Required>
</manual_config>
<profile type="OptionField">
<Required>Y</Required>
<Default>traditional</Default>
Expand Down
86 changes: 86 additions & 0 deletions net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/Menu/Menu.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

/*
* Copyright (C) 2026 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 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\Quagga\Menu;

use OPNsense\Base\Menu\MenuContainer;
use OPNsense\Core\Config;

class Menu extends MenuContainer
{
public function collect()
{
$config = Config::getInstance()->object();

if (!empty($config->OPNsense?->quagga?->general?->manual_config)) {
return;
}

$this->appendItem('Routing', 'RIP', [
'url' => '/ui/quagga/rip/index',
'fixedname' => gettext('RIP'),
'cssClass' => 'fa fa-expand fa-fw',
'order' => 10,
]);

$this->appendItem('Routing', 'OSPF', [
'url' => '/ui/quagga/ospf/index',
'fixedname' => gettext('OSPF'),
'cssClass' => 'fa fa-map fa-fw',
'order' => 20,
]);

$this->appendItem('Routing', 'OSPFv3', [
'url' => '/ui/quagga/ospf6/index',
'fixedname' => gettext('OSPFv3'),
'cssClass' => 'fa fa-map fa-fw',
'order' => 25,
]);

$this->appendItem('Routing', 'BGP', [
'url' => '/ui/quagga/bgp/index',
'fixedname' => gettext('BGP'),
'cssClass' => 'fa fa-globe fa-fw',
'order' => 40,
]);

$this->appendItem('Routing', 'BFD', [
'url' => '/ui/quagga/bfd/index',
'fixedname' => gettext('BFD'),
'cssClass' => 'fa fa-exchange fa-fw',
'order' => 50,
]);

$this->appendItem('Routing', 'STATIC', [
'url' => '/ui/quagga/static/index',
'fixedname' => gettext('STATIC'),
'cssClass' => 'fa fa-expand fa-fw',
'order' => 60,
]);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
<menu>
<Routing cssClass="fa fa-map-signs" order="45">
<General VisibleName="General" cssClass="fa fa-cog fa-fw" url="/ui/quagga/general/index" order="1"/>
<RIP VisibleName="RIP" cssClass="fa fa-expand fa-fw" url="/ui/quagga/rip/index" order="10" />
<OSPF VisibleName="OSPF" cssClass="fa fa-map fa-fw" url="/ui/quagga/ospf/index" order="20" />
<OSPFv3 VisibleName="OSPFv3" cssClass="fa fa-map fa-fw" url="/ui/quagga/ospf6/index" order="25" />
<BGP VisibleName="BGP" cssClass="fa fa-globe fa-fw" url="/ui/quagga/bgp/index" order="40" />
<BFD VisibleName="BFD" cssClass="fa fa-exchange fa-fw" url="/ui/quagga/bfd/index" order="50" />
<STATIC VisibleName="STATIC" cssClass="fa fa-expand fa-fw" url="/ui/quagga/static/index" order="60" />
<Diagnostics VisibleName="Diagnostics" cssClass="fa fa-medkit fa-fw" order="70">
<General VisibleName="General" url="/ui/quagga/diagnostics/general" order="1" />
<OSPF VisibleName="OSPF" url="/ui/quagga/diagnostics/ospf" order="20" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ POSSIBILITY OF SUCH DAMAGE.
updateServiceControlUI('quagga');
}
});

/* Manual configuration, hide all config elements except manual_config fields */
$("#general\\.manual_config").on("change", function () {
$(".manual_config_hide").closest("tr").toggle(!$(this).is(":checked"));
$(".selectpicker").selectpicker("refresh");
});
});
</script>

Expand Down
3 changes: 3 additions & 0 deletions net/frr/src/opnsense/scripts/frr/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ chown -R $user:$group /var/run/frr
touch /var/log/frr.log
chown $user:$group /var/log/frr.log

# Reload templates here since we allow manual_config
/usr/local/sbin/pluginctl -c frr_sync

# register Security Associations
/usr/local/opnsense/scripts/frr/register_sas

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
frr:/etc/rc.conf.d/frr
frr.conf:/usr/local/etc/frr/frr.conf
vtysh.conf:/usr/local/etc/frr/vtysh.conf
ospf6d_carp.conf:/usr/local/etc/frr/ospf6d_carp.conf
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
frr:/etc/rc.conf.d/frr