mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
Add staticd to routing suite (#3904)
--------- Co-authored-by: Mike Shuey <shuey@fmepnet.org>
This commit is contained in:
co-authored by
Mike Shuey
parent
5c1ecf0ba5
commit
74c1c75491
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 Deciso B.V.
|
||||
* Copyright (C) 2024 Mike Shuey
|
||||
*
|
||||
* 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\Api;
|
||||
|
||||
use OPNsense\Base\ApiMutableModelControllerBase;
|
||||
|
||||
class StaticController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'staticd';
|
||||
protected static $internalModelClass = '\OPNsense\Quagga\STATICd';
|
||||
|
||||
public function searchRouteAction()
|
||||
{
|
||||
return $this->searchBase('routes.route');
|
||||
}
|
||||
|
||||
public function getRouteAction($uuid = null)
|
||||
{
|
||||
return $this->getBase('route', 'routes.route', $uuid);
|
||||
}
|
||||
|
||||
public function setRouteAction($uuid)
|
||||
{
|
||||
return $this->setBase('route', 'routes.route', $uuid);
|
||||
}
|
||||
|
||||
public function addRouteAction()
|
||||
{
|
||||
return $this->addBase('route', 'routes.route');
|
||||
}
|
||||
|
||||
public function delRouteAction($uuid)
|
||||
{
|
||||
return $this->delBase('routes.route', $uuid);
|
||||
}
|
||||
|
||||
public function toggleRouteAction($uuid)
|
||||
{
|
||||
return $this->toggleBase('routes.route', $uuid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 Deciso B.V.
|
||||
* Copyright (C) 2024 Mike Shuey
|
||||
*
|
||||
* 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;
|
||||
|
||||
class StaticController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->staticForm = $this->getForm("static");
|
||||
$this->view->formDialogEditSTATICRoute = $this->getForm("dialogEditSTATICRoute");
|
||||
$this->view->pick('OPNsense/Quagga/static');
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>route.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>route.network</id>
|
||||
<label>Network</label>
|
||||
<type>text</type>
|
||||
<help>Defines the target for the static route, in CIDR notation.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>route.gateway</id>
|
||||
<label>Gateway (optional)</label>
|
||||
<type>text</type>
|
||||
<help>Optional gateway IP address for this route.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>route.interfacename</id>
|
||||
<label>Interface</label>
|
||||
<type>dropdown</type>
|
||||
<help>Select an interface where this settings apply to.</help>
|
||||
</field>
|
||||
</form>
|
||||
@@ -0,0 +1,8 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>staticd.enabled</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will activate the staticd service if the support of routing protocols is enabled in "General".</help>
|
||||
</field>
|
||||
</form>
|
||||
@@ -7,7 +7,8 @@
|
||||
<!--<ISIS VisibleName="IS-IS" cssClass="fa fa-bolt fa-fw" url="/ui/quagga/isis/index" order="30" />-->
|
||||
<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" />
|
||||
<Diagnostics VisibleName="Diagnostics" cssClass="fa fa-medkit fa-fw" 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" />
|
||||
<OSPFv3 VisibleName="OSPFv3" url="/ui/quagga/diagnostics/ospfv3" order="25" />
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 Deciso B.V.
|
||||
* Copyright (C) 2024 Mike Shuey
|
||||
*
|
||||
* 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;
|
||||
|
||||
use OPNsense\Base\Messages\Message;
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
/* For consistency with the other frr models, this model should be named STATIC, which is a reserved keyword */
|
||||
class STATICd extends BaseModel
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function performValidation($validateFullModel = false)
|
||||
{
|
||||
$messages = parent::performValidation($validateFullModel);
|
||||
foreach ($this->routes->route->iterateItems() as $route) {
|
||||
if (!$validateFullModel && !$route->isFieldChanged()) {
|
||||
continue;
|
||||
}
|
||||
$key = $route->__reference;
|
||||
if (!empty((string)$route->network) && !empty((string)$route->gateway)) {
|
||||
$net_proto = str_contains($route->network, ':') ? 'inet6' : 'inet';
|
||||
$gw_proto = str_contains($route->gateway, ':') ? 'inet6' : 'inet';
|
||||
if ($net_proto != $gw_proto) {
|
||||
$messages->appendMessage(
|
||||
new Message(gettext("Gateway IP protocol should match network protocol"), $key . ".gateway")
|
||||
);
|
||||
}
|
||||
}
|
||||
if (empty((string)$route->gateway) && empty((string)$route->interfacename)) {
|
||||
$messages->appendMessage(
|
||||
new Message(
|
||||
gettext("When no interface is provided, at least a gateway must be offered"),
|
||||
$key . ".gateway"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<model>
|
||||
<mount>//OPNsense/quagga/static</mount>
|
||||
<description>Staticd Routing configuration</description>
|
||||
<version>1.0.0</version>
|
||||
<items>
|
||||
<enabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<routes>
|
||||
<route type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<network type="NetworkField">
|
||||
<NetMaskRequired>Y</NetMaskRequired>
|
||||
<Required>Y</Required>
|
||||
<ValidationMessage>Specify a valid network matching the gateways ip protocol.</ValidationMessage>
|
||||
</network>
|
||||
<gateway type="NetworkField">
|
||||
<NetMaskAllowed>N</NetMaskAllowed>
|
||||
<Required>N</Required>
|
||||
</gateway>
|
||||
<interfacename type="InterfaceField">
|
||||
<multiple>N</multiple>
|
||||
<AllowDynamic>Y</AllowDynamic>
|
||||
<filters>
|
||||
<enable>/^(?!0).*$/</enable>
|
||||
<type>/^(?!group).*$/</type>
|
||||
</filters>
|
||||
</interfacename>
|
||||
</route>
|
||||
</routes>
|
||||
</items>
|
||||
</model>
|
||||
@@ -115,7 +115,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
'connected': {short: 'C', long: '{{ lang._('Connected') }}'},
|
||||
'bgp': {short: 'B', long: '{{ lang._('BGP') }}'},
|
||||
'ospf': {short: 'O', long: '{{ lang._('OSPF') }}'},
|
||||
'ospf6': {short: 'O', long: '{{ lang._('OSPFv3') }}'}
|
||||
'ospf6': {short: 'O', long: '{{ lang._('OSPFv3') }}'},
|
||||
'static': {short: 'S', long: '{{ lang._('STATIC') }}'},
|
||||
};
|
||||
let field = $("<div/>");
|
||||
if (protocols[row.protocol] !== undefined) {
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
{#
|
||||
# Copyright (c) 2024 Deciso B.V.
|
||||
# Copyright (c) 2024 by Mike Shuey
|
||||
# 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.
|
||||
#}
|
||||
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
let data_get_map = {'frm_static_settings':"/api/quagga/static/get"};
|
||||
mapDataToFormUI(data_get_map).done(function(data){
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
updateServiceControlUI('quagga');
|
||||
});
|
||||
|
||||
$("#grid-iproutes").UIBootgrid({
|
||||
'search':'/api/quagga/static/searchRoute',
|
||||
'get':'/api/quagga/static/getRoute/',
|
||||
'set':'/api/quagga/static/setRoute/',
|
||||
'add':'/api/quagga/static/addRoute/',
|
||||
'del':'/api/quagga/static/delRoute/',
|
||||
'toggle':'/api/quagga/static/toggleRoute/'
|
||||
});
|
||||
|
||||
$("#reconfigureAct").SimpleActionButton({
|
||||
onPreAction: function() {
|
||||
const dfObj = new $.Deferred();
|
||||
saveFormToEndpoint("/api/quagga/static/set", 'frm_static_settings', function () { dfObj.resolve(); }, true, function () { dfObj.reject(); });
|
||||
return dfObj;
|
||||
},
|
||||
onAction: function(data, status) {
|
||||
updateServiceControlUI('quagga');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Navigation bar -->
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" href="#general">{{ lang._('General') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#iproute">{{ lang._('Routes') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content content-box">
|
||||
<!-- general settings -->
|
||||
<div id="general" class="tab-pane fade in active">
|
||||
{{ partial("layout_partials/base_form",['fields':staticForm,'id':'frm_static_settings'])}}
|
||||
</div>
|
||||
<!-- Tab: Routes -->
|
||||
<div id="iproute" class="tab-pane fade in">
|
||||
<table id="grid-iproutes" class="table table-responsive" data-editDialog="DialogEditSTATICRoute">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
|
||||
<th data-column-id="network" data-type="string">{{ lang._('Network') }}</th>
|
||||
<th data-column-id="gateway" data-type="string">{{ lang._('Gateway') }}</th>
|
||||
<th data-column-id="interfacename" data-type="string">{{ lang._('Interface') }}</th>
|
||||
<th data-column-id="commands" data-formatter="commands">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="page-content-main">
|
||||
<div class="content-box">
|
||||
<div class="col-md-12">
|
||||
<br/>
|
||||
<button class="btn btn-primary" id="reconfigureAct"
|
||||
data-endpoint='/api/quagga/service/reconfigure'
|
||||
data-label="{{ lang._('Apply') }}"
|
||||
data-error-title="{{ lang._('Error reconfiguring STATIC') }}"
|
||||
type="button"
|
||||
></button>
|
||||
<br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEditSTATICRoute,'id':'DialogEditSTATICRoute','label':lang._('Edit Routes')])}}
|
||||
@@ -6,6 +6,7 @@ ospf6d.conf:/usr/local/etc/frr/ospf6d.conf
|
||||
ospf6d_carp.conf:/usr/local/etc/frr/ospf6d_carp.conf
|
||||
ripd.conf:/usr/local/etc/frr/ripd.conf
|
||||
sa_policies.conf:/usr/local/etc/frr/sa_policies.conf
|
||||
staticd.conf:/usr/local/etc/frr/staticd.conf
|
||||
frr:/etc/rc.conf.d/frr
|
||||
zebra.conf:/usr/local/etc/frr/zebra.conf
|
||||
vtysh.conf:/usr/local/etc/frr/vtysh.conf
|
||||
|
||||
@@ -13,6 +13,7 @@ if helpers.exists('OPNsense.quagga.bfd.enabled') and OPNsense.quagga.bfd.enabled
|
||||
if helpers.exists('OPNsense.quagga.bgp.enabled') and OPNsense.quagga.bgp.enabled == '1' %} bgpd{% endif %}{%
|
||||
if helpers.exists('OPNsense.quagga.ospf6.enabled') and OPNsense.quagga.ospf6.enabled == '1' %} ospf6d{% endif %}{%
|
||||
if helpers.exists('OPNsense.quagga.ripng.enabled') and OPNsense.quagga.ripng.enabled == '1' %} ripngd{% endif %}{%
|
||||
if helpers.exists('OPNsense.quagga.staticd.enabled') and OPNsense.quagga.staticd.enabled == '1' %} staticd{% endif %}{%
|
||||
if helpers.exists('OPNsense.quagga.isis.enabled') and OPNsense.quagga.isis.enabled == '1' %} isisd{% endif %}"
|
||||
frr_carp_demote="{%
|
||||
if not helpers.empty('OPNsense.quagga.ospf.carp_demote') %} ospfd{% endif %}{%
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
!
|
||||
! staticd Zebra config autogenerated by OPNsense
|
||||
!
|
||||
{% if not helpers.empty('OPNsense.quagga.static.enabled') %}
|
||||
{% if not helpers.empty('OPNsense.quagga.general') %}
|
||||
log syslog {{ OPNsense.quagga.general.sysloglevel }}
|
||||
{% endif %}
|
||||
{% if not helpers.empty('OPNsense.quagga.general.profile') %}
|
||||
frr defaults {{ OPNsense.quagga.general.profile }}
|
||||
{% endif %}
|
||||
!
|
||||
{% for route in helpers.toList('OPNsense.quagga.static.routes.route') %}
|
||||
{% if route.enabled == '1' %}
|
||||
{% if ':' in route.network %}ipv6{% else %}ip{% endif %} route {{ route.network }} {{ route.gateway|default('')}} {{ helpers.physical_interface(route.interfacename) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
!
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user