net/quagga: merge version 1.3.1 from master

This commit is contained in:
Franco Fichtner 2017-07-13 08:21:15 +02:00
parent dabeb8b25a
commit b6e79be755
26 changed files with 907 additions and 62 deletions

View file

@ -1,6 +1,5 @@
PLUGIN_NAME= quagga
PLUGIN_VERSION= 1.2.0
PLUGIN_REVISION= 1
PLUGIN_VERSION= 1.3.1
PLUGIN_COMMENT= Quagga Routing Suite
PLUGIN_DEPENDS= quagga ruby
PLUGIN_MAINTAINER= franz.fabian.94@gmail.com

View file

@ -1,12 +1,4 @@
<?php
namespace OPNsense\Quagga\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Quagga\BGP;
use \OPNsense\Core\Config;
use \OPNsense\Base\ApiMutableModelControllerBase;
use \OPNsense\Base\UIModelGrid;
/**
* Copyright (C) 2015 - 2017 Deciso B.V.
* Copyright (C) 2017 Fabian Franz
@ -36,6 +28,14 @@ use \OPNsense\Base\UIModelGrid;
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Quagga\Api;
use \OPNsense\Quagga\BGP;
use \OPNsense\Core\Config;
use \OPNsense\Base\ApiMutableModelControllerBase;
use \OPNsense\Base\UIModelGrid;
class BgpController extends ApiMutableModelControllerBase
{
static protected $internalModelName = 'BGP';
@ -82,7 +82,7 @@ class BgpController extends ApiMutableModelControllerBase
$grid = new UIModelGrid($mdlBGP->neighbors->neighbor);
return $grid->fetchBindRequest(
$this->request,
array("enabled", "address", "remoteas", "updatesource", "nexthopself", "defaultoriginate" )
array("enabled", "address", "remoteas", "updatesource", "nexthopself", "defaultoriginate", "linkedPrefixlistIn", "linkedPrefixlistOut", "linkedRoutemapIn", "linkedRoutemapOut" )
);
}
@ -120,6 +120,7 @@ class BgpController extends ApiMutableModelControllerBase
// save config if validated correctly
$mdlBGP->serializeToConfig();
Config::getInstance()->save();
unset($result['validations']);
$result["result"] = "saved";
}
}
@ -172,6 +173,293 @@ class BgpController extends ApiMutableModelControllerBase
return array("result" => "failed");
}
public function searchAspathAction()
{
$this->sessionClose();
$mdlBGP = $this->getModel();
$grid = new UIModelGrid($mdlBGP->aspaths->aspath);
return $grid->fetchBindRequest(
$this->request,
array("enabled", "number", "action", "as" )
);
}
public function getAspathAction($uuid = null)
{
$mdlBGP = $this->getModel();
if ($uuid != null) {
$node = $mdlBGP->getNodeByReference('aspaths.aspath.' . $uuid);
if ($node != null) {
// return node
return array("aspath" => $node->getNodes());
}
} else {
$node = $mdlBGP->aspaths->aspath->add();
return array("aspath" => $node->getNodes());
}
return array();
}
public function addAspathAction()
{
$result = array("result" => "failed");
if ($this->request->isPost() && $this->request->hasPost("aspath")) {
$result = array("result" => "failed", "validations" => array());
$mdlBGP = $this->getModel();
$node = $mdlBGP->aspaths->aspath->Add();
$node->setNodes($this->request->getPost("aspath"));
$valMsgs = $mdlBGP->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, "aspath", $msg->getField());
$result["validations"][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdlBGP->serializeToConfig();
Config::getInstance()->save();
unset($result['validations']);
$result["result"] = "saved";
}
}
return $result;
}
public function delAspathAction($uuid)
{
$result = array("result" => "failed");
if ($this->request->isPost()) {
$mdlBGP = $this->getModel();
if ($uuid != null) {
if ($mdlBGP->aspaths->aspath->del($uuid)) {
$mdlBGP->serializeToConfig();
Config::getInstance()->save();
$result['result'] = 'deleted';
} else {
$result['result'] = 'not found';
}
}
}
return $result;
}
public function setAspathAction($uuid)
{
if ($this->request->isPost() && $this->request->hasPost("aspath")) {
$mdlNeighbor = $this->getModel();
if ($uuid != null) {
$node = $mdlNeighbor->getNodeByReference('aspaths.aspath.' . $uuid);
if ($node != null) {
$result = array("result" => "failed", "validations" => array());
$aspathInfo = $this->request->getPost("aspath");
$node->setNodes($aspathInfo);
$valMsgs = $mdlNeighbor->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, "aspath", $msg->getField());
$result["validations"][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdlNeighbor->serializeToConfig();
Config::getInstance()->save();
$result = array("result" => "saved");
}
return $result;
}
}
}
return array("result" => "failed");
}
public function searchPrefixlistAction()
{
$this->sessionClose();
$mdlBGP = $this->getModel();
$grid = new UIModelGrid($mdlBGP->prefixlists->prefixlist);
return $grid->fetchBindRequest(
$this->request,
array("enabled", "name", "seqnumber", "action", "network" )
);
}
public function getPrefixlistAction($uuid = null)
{
$mdlBGP = $this->getModel();
if ($uuid != null) {
$node = $mdlBGP->getNodeByReference('prefixlists.prefixlist.' . $uuid);
if ($node != null) {
// return node
return array("prefixlist" => $node->getNodes());
}
} else {
$node = $mdlBGP->prefixlists->prefixlist->add();
return array("prefixlist" => $node->getNodes());
}
return array();
}
public function addPrefixlistAction()
{
$result = array("result" => "failed");
if ($this->request->isPost() && $this->request->hasPost("prefixlist")) {
$result = array("result" => "failed", "validations" => array());
$mdlBGP = $this->getModel();
$node = $mdlBGP->prefixlists->prefixlist->Add();
$node->setNodes($this->request->getPost("prefixlist"));
$valMsgs = $mdlBGP->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, "prefixlist", $msg->getField());
$result["validations"][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdlBGP->serializeToConfig();
Config::getInstance()->save();
unset($result['validations']);
$result["result"] = "saved";
}
}
return $result;
}
public function delPrefixlistAction($uuid)
{
$result = array("result" => "failed");
if ($this->request->isPost()) {
$mdlBGP = $this->getModel();
if ($uuid != null) {
if ($mdlBGP->prefixlists->prefixlist->del($uuid)) {
$mdlBGP->serializeToConfig();
Config::getInstance()->save();
$result['result'] = 'deleted';
} else {
$result['result'] = 'not found';
}
}
}
return $result;
}
public function setPrefixlistAction($uuid)
{
if ($this->request->isPost() && $this->request->hasPost("prefixlist")) {
$mdlNeighbor = $this->getModel();
if ($uuid != null) {
$node = $mdlNeighbor->getNodeByReference('prefixlists.prefixlist.' . $uuid);
if ($node != null) {
$result = array("result" => "failed", "validations" => array());
$prefixlistInfo = $this->request->getPost("prefixlist");
$node->setNodes($prefixlistInfo);
$valMsgs = $mdlNeighbor->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, "prefixlist", $msg->getField());
$result["validations"][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdlNeighbor->serializeToConfig();
Config::getInstance()->save();
$result = array("result" => "saved");
}
return $result;
}
}
}
return array("result" => "failed");
}
public function searchRoutemapAction()
{
$this->sessionClose();
$mdlBGP = $this->getModel();
$grid = new UIModelGrid($mdlBGP->routemaps->routemap);
return $grid->fetchBindRequest(
$this->request,
array("enabled", "name", "action", "id", "match", "set" )
);
}
public function getRoutemapAction($uuid = null)
{
$mdlBGP = $this->getModel();
if ($uuid != null) {
$node = $mdlBGP->getNodeByReference('routemaps.routemap.' . $uuid);
if ($node != null) {
// return node
return array("routemap" => $node->getNodes());
}
} else {
$node = $mdlBGP->routemaps->routemap->add();
return array("routemap" => $node->getNodes());
}
return array();
}
public function addRoutemapAction()
{
$result = array("result" => "failed");
if ($this->request->isPost() && $this->request->hasPost("routemap")) {
$result = array("result" => "failed", "validations" => array());
$mdlBGP = $this->getModel();
$node = $mdlBGP->routemaps->routemap->Add();
$node->setNodes($this->request->getPost("routemap"));
$valMsgs = $mdlBGP->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, "routemap", $msg->getField());
$result["validations"][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdlBGP->serializeToConfig();
Config::getInstance()->save();
unset($result['validations']);
$result["result"] = "saved";
}
}
return $result;
}
public function delRoutemapAction($uuid)
{
$result = array("result" => "failed");
if ($this->request->isPost()) {
$mdlBGP = $this->getModel();
if ($uuid != null) {
if ($mdlBGP->routemaps->routemap->del($uuid)) {
$mdlBGP->serializeToConfig();
Config::getInstance()->save();
$result['result'] = 'deleted';
} else {
$result['result'] = 'not found';
}
}
}
return $result;
}
public function setRoutemapAction($uuid)
{
if ($this->request->isPost() && $this->request->hasPost("routemap")) {
$mdlNeighbor = $this->getModel();
if ($uuid != null) {
$node = $mdlNeighbor->getNodeByReference('routemaps.routemap.' . $uuid);
if ($node != null) {
$result = array("result" => "failed", "validations" => array());
$routemapInfo = $this->request->getPost("routemap");
$node->setNodes($routemapInfo);
$valMsgs = $mdlNeighbor->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, "routemap", $msg->getField());
$result["validations"][$fieldnm] = $msg->getMessage();
}
if (count($result['validations']) == 0) {
// save config if validated correctly
$mdlNeighbor->serializeToConfig();
Config::getInstance()->save();
$result = array("result" => "saved");
}
return $result;
}
}
}
return array("result" => "failed");
}
public function toggle_handler($uuid, $elements, $element)
{
$result = array("result" => "failed");
@ -200,4 +488,19 @@ class BgpController extends ApiMutableModelControllerBase
{
return $this->toggle_handler($uuid, 'neighbors', 'neighbor');
}
public function toggleAspathAction($uuid)
{
return $this->toggle_handler($uuid, 'aspaths', 'aspath');
}
public function togglePrefixlistAction($uuid)
{
return $this->toggle_handler($uuid, 'prefixlists', 'prefixlist');
}
public function toggleRoutemapAction($uuid)
{
return $this->toggle_handler($uuid, 'routemaps', 'routemap');
}
}

View file

@ -29,6 +29,7 @@
*/
namespace OPNsense\Quagga\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Core\Backend;
use \OPNsense\Core\Config;
@ -59,6 +60,12 @@ class DiagnosticsController extends ApiControllerBase
$response = $backend->configdRun("quagga diag-bgp summary");
return array("response" => $response);
}
public function showrunningconfigAction()
{
$backend = new Backend();
$response = $backend->configdRun("quagga general-runningconfig");
return array("response" => $response);
}
private function get_ospf_information($name)
{
$backend = new Backend();

View file

@ -27,8 +27,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Quagga\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Quagga\General;
use \OPNsense\Core\Config;

View file

@ -31,6 +31,7 @@
*/
namespace OPNsense\Quagga\Api;
use \OPNsense\Quagga\OSPF6;
use \OPNsense\Core\Config;
use \OPNsense\Base\ApiMutableModelControllerBase;

View file

@ -30,6 +30,7 @@
*/
namespace OPNsense\Quagga\Api;
use \OPNsense\Quagga\OSPF;
use \OPNsense\Core\Config;
use \OPNsense\Base\ApiMutableModelControllerBase;

View file

@ -29,6 +29,7 @@
*/
namespace OPNsense\Quagga\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Quagga\RIP;
use \OPNsense\Core\Config;

View file

@ -29,6 +29,7 @@
*/
namespace OPNsense\Quagga\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Core\Backend;
use \OPNsense\Quagga\General;

View file

@ -1,6 +1,4 @@
<?php
namespace OPNsense\Quagga;
/*
Copyright (C) 2017 Fabian Franz
Copyright (C) 2017 Michael Muenz
@ -23,6 +21,9 @@ namespace OPNsense\Quagga;
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Quagga;
class BgpController extends \OPNsense\Base\IndexController
{
public function indexAction()
@ -30,6 +31,9 @@ class BgpController extends \OPNsense\Base\IndexController
$this->view->title = gettext("BGP Settings");
$this->view->bgpForm = $this->getForm("bgp");
$this->view->formDialogEditBGPNeighbor = $this->getForm("dialogEditBGPNeighbor");
$this->view->formDialogEditBGPASPaths = $this->getForm("dialogEditBGPASPath");
$this->view->formDialogEditBGPPrefixLists = $this->getForm("dialogEditBGPPrefixLists");
$this->view->formDialogEditBGPRouteMaps = $this->getForm("dialogEditBGPRouteMaps");
$this->view->pick('OPNsense/Quagga/bgp');
}
}

View file

@ -1,6 +1,4 @@
<?php
namespace OPNsense\Quagga;
/*
Copyright (C) 2017 Fabian Franz
All rights reserved.
@ -27,6 +25,8 @@ namespace OPNsense\Quagga;
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Quagga;
class GeneralController extends \OPNsense\Base\IndexController
{
public function indexAction()

View file

@ -1,4 +1,30 @@
<?php
/*
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 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 IsisController extends \OPNsense\Base\IndexController

View file

@ -1,4 +1,30 @@
<?php
/*
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 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 RipController extends \OPNsense\Base\IndexController

View file

@ -0,0 +1,26 @@
<form>
<field>
<id>aspath.enabled</id>
<label>Enabled</label>
<type>checkbox</type>
<help>Enable / Disable</help>
</field>
<field>
<id>aspath.number</id>
<label>Number</label>
<type>text</type>
<help>The ACL rule number (10-99); keep in mind that there are no sequence numbers with AS-Path lists. When you want to add a new line between you have to completely remove the ACL!</help>
</field>
<field>
<id>aspath.action</id>
<label>Action</label>
<type>select_multiple</type>
<help>Set permit for match or deny to negate the rule.</help>
</field>
<field>
<id>aspath.as</id>
<label>AS</label>
<type>text</type>
<help>The AS pattern you want to match, regexp allowed (e.g. .$ or _1$). It's not validated so please be careful!</help>
</field>
</form>

View file

@ -32,4 +32,28 @@
<label>Send Defaultroute</label>
<type>checkbox</type>
</field>
<field>
<id>neighbor.linkedPrefixlistIn</id>
<label>Prefix-List In</label>
<type>dropdown</type>
<help>Prefix-List for inbound direction</help>
</field>
<field>
<id>neighbor.linkedPrefixlistOut</id>
<label>Prefix-List Out</label>
<type>dropdown</type>
<help>Prefix-List for outbound direction</help>
</field>
<field>
<id>neighbor.linkedRoutemapIn</id>
<label>Route-Map In</label>
<type>dropdown</type>
<help>Route-Map for inbound direction</help>
</field>
<field>
<id>neighbor.linkedRoutemapOut</id>
<label>Route-Map Out</label>
<type>dropdown</type>
<help>Route-Map for outbound direction</help>
</field>
</form>

View file

@ -0,0 +1,32 @@
<form>
<field>
<id>prefixlist.enabled</id>
<label>Enabled</label>
<type>checkbox</type>
<help>Enable / Disable</help>
</field>
<field>
<id>prefixlist.name</id>
<label>Name</label>
<type>text</type>
<help>The name of your Prefix-List, please choose one near to the result you want to achieve.</help>
</field>
<field>
<id>prefixlist.seqnumber</id>
<label>Number</label>
<type>text</type>
<help>The ACL sequence number (10-99)</help>
</field>
<field>
<id>prefixlist.action</id>
<label>Action</label>
<type>select_multiple</type>
<help>Set permit for match or deny to negate the rule.</help>
</field>
<field>
<id>prefixlist.network</id>
<label>Network</label>
<type>text</type>
<help>The network pattern you want to match. You can also add "ge" or "le" additions after the network statement. It's not validated so please be careful!</help>
</field>
</form>

View file

@ -0,0 +1,40 @@
<form>
<field>
<id>routemap.enabled</id>
<label>Enabled</label>
<type>checkbox</type>
<help>Enable / Disable</help>
</field>
<field>
<id>routemap.name</id>
<label>Name</label>
<type>text</type>
<help>Route-map name to match and set your patterns, it will be enabled via the neigbor configuration.</help>
</field>
<field>
<id>routemap.action</id>
<label>Action</label>
<type>select_multiple</type>
<help>Set permit for match or deny to negate the rule.</help>
</field>
<field>
<id>routemap.id</id>
<label>ID</label>
<type>text</type>
<help>Route-map ID between 10 and 99. Be aware that the sorting will be done under the hood, so when you add an entry between it get's to the right position</help>
</field>
<field>
<id>routemap.match</id>
<label>AS-Path List</label>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
<help>Select the AS-Path list</help>
</field>
<field>
<id>routemap.set</id>
<label>Set</label>
<type>text</type>
<help>Free text field for your set, please be careful! You can set e.g. "local-prefernce 300" or "community 1:1" (http://www.nongnu.org/quagga/docs/docs-multi/Route-Map-Set-Command.html#Route-Map-Set-Command)</help>
</field>
</form>

View file

@ -6,9 +6,11 @@
<default>0</default>
<Required>Y</Required>
</enabled>
<asnumber type="TextField">
<asnumber type="IntegerField">
<default></default>
<Required>Y</Required>
<MinimumValue>1</MinimumValue>
<MaximumValue>4294967295</MaximumValue>
</asnumber>
<networks type="CSVListField">
<default></default>
@ -25,7 +27,6 @@
<connected>Connected routes (directly attached subnet or host)</connected>
<isis>Intermediate System to Intermediate System (IS-IS)</isis>
<kernel>Kernel routes (not installed via the zebra RIB)</kernel>
<pim>Protocol Independent Multicast (PIM)</pim>
<rip>Routing Information Protocol (RIP)</rip>
<static>Statically configured routes</static>
</OptionValues>
@ -41,9 +42,11 @@
<Required>Y</Required>
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
</address>
<remoteas type="TextField">
<remoteas type="IntegerField">
<default></default>
<Required>Y</Required>
<MinimumValue>1</MinimumValue>
<MaximumValue>4294967295</MaximumValue>
</remoteas>
<updatesource type="InterfaceField">
<default></default>
@ -53,15 +56,165 @@
<enable>/^(?!0).*$/</enable>
</filters>
</updatesource>
<nexthopself type="BooleanField">
<nexthopself type="BooleanField">
<default>0</default>
<Required>N</Required>
</nexthopself>
<defaultoriginate type="BooleanField">
<defaultoriginate type="BooleanField">
<default>0</default>
<Required>N</Required>
</defaultoriginate>
</neighbor>
<linkedPrefixlistIn type="ModelRelationField">
<Model>
<template>
<source>OPNsense.quagga.bgp</source>
<items>prefixlists.prefixlist</items>
<display>name</display>
<group>name</group>
</template>
</Model>
<ValidationMessage>Related Prefix-List item not found</ValidationMessage>
<Multiple>N</Multiple>
<Required>N</Required>
</linkedPrefixlistIn>
<linkedPrefixlistOut type="ModelRelationField">
<Model>
<template>
<source>OPNsense.quagga.bgp</source>
<items>prefixlists.prefixlist</items>
<display>name</display>
<group>name</group>
</template>
</Model>
<ValidationMessage>Related Prefix-List item not found</ValidationMessage>
<Multiple>N</Multiple>
<Required>N</Required>
</linkedPrefixlistOut>
<linkedRoutemapIn type="ModelRelationField">
<Model>
<template>
<source>OPNsense.quagga.bgp</source>
<items>routemaps.routemap</items>
<display>name</display>
<group>name</group>
</template>
</Model>
<ValidationMessage>Related Route-Map item not found</ValidationMessage>
<Multiple>N</Multiple>
<Required>N</Required>
</linkedRoutemapIn>
<linkedRoutemapOut type="ModelRelationField">
<Model>
<template>
<source>OPNsense.quagga.bgp</source>
<items>routemaps.routemap</items>
<display>name</display>
<group>name</group>
</template>
</Model>
<ValidationMessage>Related Route-Map item not found</ValidationMessage>
<Multiple>N</Multiple>
<Required>N</Required>
</linkedRoutemapOut>
</neighbor>
</neighbors>
<aspaths>
<aspath type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<number type="IntegerField">
<default></default>
<Required>Y</Required>
<MinimumValue>10</MinimumValue>
<MaximumValue>99</MaximumValue>
</number>
<action type="OptionField">
<default></default>
<Required>Y</Required>
<OptionValues>
<permit>Permit</permit>
<deny>Deny</deny>
</OptionValues>
</action>
<as type="TextField">
<default></default>
<Required>Y</Required>
</as>
</aspath>
</aspaths>
<prefixlists>
<prefixlist type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<name type="TextField">
<default></default>
<Required>Y</Required>
</name>
<seqnumber type="IntegerField">
<default></default>
<Required>Y</Required>
<MinimumValue>10</MinimumValue>
<MaximumValue>99</MaximumValue>
</seqnumber>
<action type="OptionField">
<default></default>
<Required>Y</Required>
<OptionValues>
<permit>Permit</permit>
<deny>Deny</deny>
</OptionValues>
</action>
<network type="TextField">
<default></default>
<Required>Y</Required>
</network>
</prefixlist>
</prefixlists>
<routemaps>
<routemap type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<name type="TextField">
<default></default>
<Required>Y</Required>
</name>
<action type="OptionField">
<default></default>
<Required>Y</Required>
<OptionValues>
<permit>Permit</permit>
<deny>Deny</deny>
</OptionValues>
</action>
<id type="IntegerField">
<default></default>
<Required>Y</Required>
<MinimumValue>10</MinimumValue>
<MaximumValue>99</MaximumValue>
</id>
<match type="ModelRelationField">
<Model>
<template>
<source>OPNsense.quagga.bgp</source>
<items>aspaths.aspath</items>
<display>number</display>
</template>
</Model>
<ValidationMessage>Related item not found</ValidationMessage>
<Multiple>Y</Multiple>
<Required>N</Required>
</match>
<set type="TextField">
<default></default>
<Required>Y</Required>
</set>
</routemap>
</routemaps>
</items>
</model>

View file

@ -22,6 +22,7 @@
POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Quagga;
use OPNsense\Base\BaseModel;
class OSPF6 extends BaseModel

View file

@ -31,6 +31,9 @@ POSSIBILITY OF SUCH DAMAGE.
<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="#neighbors">{{ lang._('Neighbors') }}</a></li>
<li><a data-toggle="tab" href="#aspaths">{{ lang._('AS Path Lists') }}</a></li>
<li><a data-toggle="tab" href="#prefixlists">{{ lang._('Prefix Lists') }}</a></li>
<li><a data-toggle="tab" href="#routemaps">{{ lang._('Route Maps') }}</a></li>
</ul>
<div class="tab-content content-box tab-content">
<div id="general" class="tab-pane fade in active">
@ -43,8 +46,6 @@ POSSIBILITY OF SUCH DAMAGE.
</div>
</div>
</div>
<div id="neighbors" class="tab-pane fade in">
<table id="grid-neighbors" class="table table-responsive" data-editDialog="DialogEditBGPNeighbor">
<thead>
@ -55,6 +56,10 @@ POSSIBILITY OF SUCH DAMAGE.
<th data-column-id="updatesource" data-type="string" data-visible="true">{{ lang._('Update Source Address') }}</th>
<th data-column-id="nexthopself" data-type="string" data-formatter="rowtoggle">{{ lang._('Next Hop Self') }}</th>
<th data-column-id="defaultoriginate" data-type="string" data-formatter="rowtoggle">{{ lang._('Default Originate') }}</th>
<th data-column-id="linkedPrefixlistIn" data-type="string" data-visible="true">{{ lang._('Prefix List inbound') }}</th>
<th data-column-id="linkedPrefixlistOut" data-type="string" data-visible="true">{{ lang._('Prefix List outbound') }}</th>
<th data-column-id="linkedRoutemapIn" data-type="string" data-visible="true">{{ lang._('Route Map inbound') }}</th>
<th data-column-id="linkedRoutemapOut" data-type="string" data-visible="true">{{ lang._('Route Map outbound') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
@ -72,6 +77,83 @@ POSSIBILITY OF SUCH DAMAGE.
</tfoot>
</table>
</div>
<div id="aspaths" class="tab-pane fade in">
<table id="grid-aspaths" class="table table-responsive" data-editDialog="DialogEditBGPASPaths">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle" data-sortable="false">{{ lang._('Enabled') }}</th>
<th data-column-id="number" data-type="string" data-visible="true" data-sortable="true">{{ lang._('Number') }}</th>
<th data-column-id="action" data-type="string" data-visible="true" data-sortable="false">{{ lang._('Action') }}</th>
<th data-column-id="as" data-type="string" data-visible="true" data-sortable="false">{{ lang._('AS Number') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="5"></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 id="prefixlists" class="tab-pane fade in">
<table id="grid-prefixlists" class="table table-responsive" data-editDialog="DialogEditBGPPrefixLists">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle" data-sortable="false">{{ lang._('Enabled') }}</th>
<th data-column-id="name" data-type="string" data-visible="true" data-sortable="true">{{ lang._('Name') }}</th>
<th data-column-id="seqnumber" data-type="string" data-visible="true" data-sortable="true">{{ lang._('Secquence Number') }}</th>
<th data-column-id="action" data-type="string" data-visible="true" data-sortable="false">{{ lang._('Action') }}</th>
<th data-column-id="network" data-type="string" data-visible="true" data-sortable="false">{{ lang._('Network') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="5"></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 id="routemaps" class="tab-pane fade in">
<table id="grid-routemaps" class="table table-responsive" data-editDialog="DialogEditBGPRouteMaps">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="name" data-type="string" data-visible="true">{{ lang._('Name') }}</th>
<th data-column-id="action" data-type="string" data-visible="true">{{ lang._('Action') }}</th>
<th data-column-id="id" data-type="string" data-visible="true">{{ lang._('ID') }}</th>
<th data-column-id="match" data-type="string" data-visible="true">{{ lang._('AS Path List') }}</th>
<th data-column-id="set" data-type="string" data-visible="true">{{ lang._('Set') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="5"></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
<script type="text/javascript">
@ -105,8 +187,40 @@ $(document).ready(function() {
'options':{selection:false, multiSelect:false}
}
);
$("#grid-aspaths").UIBootgrid(
{ 'search':'/api/quagga/bgp/searchAspath',
'get':'/api/quagga/bgp/getAspath/',
'set':'/api/quagga/bgp/setAspath/',
'add':'/api/quagga/bgp/addAspath/',
'del':'/api/quagga/bgp/delAspath/',
'toggle':'/api/quagga/bgp/toggleAspath/',
'options':{selection:false, multiSelect:false}
}
);
$("#grid-prefixlists").UIBootgrid(
{ 'search':'/api/quagga/bgp/searchPrefixlist',
'get':'/api/quagga/bgp/getPrefixlist/',
'set':'/api/quagga/bgp/setPrefixlist/',
'add':'/api/quagga/bgp/addPrefixlist/',
'del':'/api/quagga/bgp/delPrefixlist/',
'toggle':'/api/quagga/bgp/togglePrefixlist/',
'options':{selection:false, multiSelect:false}
}
);
$("#grid-routemaps").UIBootgrid(
{ 'search':'/api/quagga/bgp/searchRoutemap',
'get':'/api/quagga/bgp/getRoutemap/',
'set':'/api/quagga/bgp/setRoutemap/',
'add':'/api/quagga/bgp/addRoutemap/',
'del':'/api/quagga/bgp/delRoutemap/',
'toggle':'/api/quagga/bgp/toggleRoutemap/',
'options':{selection:false, multiSelect:false}
}
);
});
</script>
{{ partial("layout_partials/base_dialog",['fields':formDialogEditBGPNeighbor,'id':'DialogEditBGPNeighbor','label':lang._('Edit Neighbor')])}}
{{ partial("layout_partials/base_dialog",['fields':formDialogEditBGPASPaths,'id':'DialogEditBGPASPaths','label':lang._('Edit AS Paths')])}}
{{ partial("layout_partials/base_dialog",['fields':formDialogEditBGPPrefixLists,'id':'DialogEditBGPPrefixLists','label':lang._('Edit Prefix Lists')])}}
{{ partial("layout_partials/base_dialog",['fields':formDialogEditBGPRouteMaps,'id':'DialogEditBGPRouteMaps','label':lang._('Edit Route Maps')])}}

View file

@ -109,7 +109,9 @@ $(document).ready(function() {
$('#routing6').html(content)
//$('#routing6 table').bootgrid({converters: dataconverters})
});
ajaxCall(url="/api/quagga/diagnostics/showrunningconfig", sendData={}, callback=function(data,status) {
$("#runningconfig").text(data['response']);
});
});
</script>
@ -118,9 +120,13 @@ $(document).ready(function() {
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
<li class="active"><a data-toggle="tab" href="#routing">{{ lang._('IPv4 Routes') }}</a></li>
<li><a data-toggle="tab" href="#routing6">{{ lang._('IPv6 Routes') }}</a></li>
<li><a data-toggle="tab" href="#showrun">{{ lang._('Running Configuration') }}</a></li>
</ul>
<div class="tab-content content-box tab-content">
<div id="routing" class="tab-pane fade in active"></div>
<div id="routing6" class="tab-pane fade in"></div>
<div id="showrun" class="tab-pane fade in">
<pre id="runningconfig"></pre>
</div>
</div>

View file

@ -32,51 +32,51 @@ POSSIBILITY OF SUCH DAMAGE.
<table class="table table-striped">
<tbody>
<tr>
<td>{{ lang._("RFC2328 Conform") }}</td>
<td>{{ lang._('RFC2328 Conform') }}</td>
<td><%= checkmark(ospf_overview['rfc2328_conform']) %></td>
</tr>
<tr>
<td>{{ lang._("ASBR") }}</td>
<td>{{ lang._('ASBR') }}</td>
<td><%= checkmark(ospf_overview['asbr']) %></td>
</tr>
<tr>
<td>{{ lang._("Router ID") }}</td>
<td>{{ lang._('Router ID') }}</td>
<td><%= ospf_overview['router_id'] %></td>
</tr>
<tr>
<td>{{ lang._("RFC1583 Compatibility") }}</td>
<td>{{ lang._('RFC1583 Compatibility') }}</td>
<td><%= checkmark(ospf_overview['rfc1583_compatibility']) %></td>
</tr>
<tr>
<td>{{ lang._("Opaque Capability") }}</td>
<td>{{ lang._('Opaque Capability') }}</td>
<td><%= checkmark(ospf_overview['opaque_capability']) %></td>
</tr>
<tr>
<td>{{ lang._("Initial SPF Scheduling Delay") }}</td>
<td>{{ lang._('Initial SPF Scheduling Delay') }}</td>
<td><%= ospf_overview['initial_spf_scheduling_delay'] %></td>
</tr>
<tr>
<td>{{ lang._("Minimum Hold Time") }}</td>
<td>{{ lang._('Minimum Hold Time') }}</td>
<td><%= ospf_overview['hold_time']['min'] %> {{ lang._('Milliseconds') }}</td>
</tr>
<tr>
<td>{{ lang._("Maximum Hold Time") }}</td>
<td>{{ lang._('Maximum Hold Time') }}</td>
<td><%= ospf_overview['hold_time']['max'] %> {{ lang._('Milliseconds') }}</td>
</tr>
<tr>
<td>{{ lang._("Current Hold Time Multipier") }}</td>
<td>{{ lang._('Current Hold Time Multipier') }}</td>
<td><%= ospf_overview['current_hold_time_multipier'] %></td>
</tr>
<tr>
<td>{{ lang._("SPF Timer") }}</td>
<td>{{ lang._('SPF Timer') }}</td>
<td><%= ospf_overview['spf_timer'] %></td>
</tr>
<tr>
<td>{{ lang._("Refresh Timer") }}</td>
<td>{{ lang._('Refresh Timer') }}</td>
<td><%= ospf_overview['refresh_timer'] %></td>
</tr>
<tr>
<td>{{ lang._("Areas Attached Count") }}</td>
<td>{{ lang._('Areas Attached Count') }}</td>
<td><%= ospf_overview['areas_attached_count'] %></td>
</tr>
</tbody>

View file

@ -32,38 +32,38 @@ POSSIBILITY OF SUCH DAMAGE.
<table class="table table-striped">
<tbody>
<tr>
<td>{{ lang._("Router ID") }}</td>
<td>{{ lang._('Router ID') }}</td>
<td><%= ospfv3_overview['router_id'] %></td>
</tr>
<tr>
<td>{{ lang._("Routing Process") }}</td>
<td>{{ lang._('Routing Process') }}</td>
<td><%= ospfv3_overview['routing_process'] %></td>
</tr>
<tr>
<td>{{ lang._("Running Time") }}</td>
<td>{{ lang._('Running Time') }}</td>
<td><%= ospfv3_overview['running_time'] %></td>
</tr>
<tr>
<td>{{ lang._("Initial SPF scheduling delay") }}</td>
<td>{{ lang._('Initial SPF scheduling delay') }}</td>
<td><%= ospfv3_overview['intital_spf_scheduling_delay'] %></td>
</tr>
<tr>
<td>{{ lang._("Hold Time") }}</td>
<td>{{ lang._('Hold Time') }}</td>
<td>
{{ lang._("Minimum Hold Time") }} <%= ospfv3_overview['hold_time']['min'] %><br/>
{{ lang._("Maximum Hold Time:") }} <%= ospfv3_overview['hold_time']['max'] %>
{{ lang._('Minimum Hold Time') }} <%= ospfv3_overview['hold_time']['min'] %><br/>
{{ lang._('Maximum Hold Time:') }} <%= ospfv3_overview['hold_time']['max'] %>
</td>
</tr>
<tr>
<td>{{ lang._("SPF timer") }}</td>
<td>{{ lang._('SPF timer') }}</td>
<td><%= ospfv3_overview['spf_timer'] %></td>
</tr>
<tr>
<td>{{ lang._("Number Of Scoped AS") }}</td>
<td>{{ lang._('Number Of Scoped AS') }}</td>
<td><%= ospfv3_overview['number_as_scoped'] %></td>
</tr>
<tr>
<td>{{ lang._("Number Of Areas") }}</td>
<td>{{ lang._('Number Of Areas') }}</td>
<td><%= ospfv3_overview['number_of_areas'] %></td>
</tr>
</tbody>
@ -77,11 +77,11 @@ POSSIBILITY OF SUCH DAMAGE.
<table class="table table-striped">
<tbody>
<tr>
<td>{{ lang._("Number Of LSAs") }}</td>
<td>{{ lang._('Number Of LSAs') }}</td>
<td><%= area['number_lsas'] %></td>
</tr>
<tr>
<td>{{ lang._("Interfaces") }}</td>
<td>{{ lang._('Interfaces') }}</td>
<td><%= _.join(area['interfaces'], ", ") %></td>
</tr>
</tbody>
@ -184,7 +184,7 @@ POSSIBILITY OF SUCH DAMAGE.
<% }) %>
<% } %>
<% if (ospfv3_database['as_scoped']) { %>
<h2>{{ lang._('AS Scpoed') }}</h2>
<h2>{{ lang._('AS Scoped') }}</h2>
<table>
<thead>
<tr>
@ -235,7 +235,7 @@ POSSIBILITY OF SUCH DAMAGE.
<% } else if (propertyname == 'area_cost') { %>
<% _.each(int[propertyname], function (ac) { %>
<%= ac['area'] %>: <%= ac['cost'] %><br />
<% }) %>
<% }) %>
<% } else { %>
<%= translate(int[propertyname]) %>
<% } %>

View file

@ -52,7 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="interfacename" data-type="string" data-visible="true">{{ lang._('Interface Name') }}</th>
<th data-column-id="area" data-type="string" data-visible="true">{{ lang._('Area') }}</th>
<th data-column-id="area" data-type="string" data-visible="true">{{ lang._('Area') }}</th>
<th data-column-id="networktype" data-type="string" data-visible="true">{{ lang._('Network Type') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>

View file

@ -124,7 +124,7 @@ class General
end
entries
end
def routes6
routes(true)
end
@ -432,7 +432,7 @@ class OSPFv3
def initialize(sh)
@vtysh = sh
end
def overview
lines = @vtysh.execute("show ipv6 ospf6").lines
overview = {}
@ -485,11 +485,11 @@ class OSPFv3
end
overview
end
def linkstate
lines = @vtysh.execute("show ipv6 ospf6 linkstate").lines
linkstate = {}
qta = nil
current_area = []
while line = lines.shift&.strip
@ -507,11 +507,11 @@ class OSPFv3
end
linkstate
end
def route
route = []
lines = @vtysh.execute("show ipv6 ospf6 route").lines
lines.each do |line|
f1, f2, network, gateway, interface, time = line.strip.split(/\s+/)
route << { f1: f1,
@ -523,7 +523,7 @@ class OSPFv3
end
route
end
def neighbor
qta = QuaggaTableReader.new(["Neighbor ID","Pri", "DeadTime", "State/IfState", "Duration I/F[State]"])
neighbor = []
@ -571,7 +571,7 @@ class OSPFv3
end
database
end
def interface
lines = @vtysh.execute("show ipv6 ospf6 interface").lines
int = {}
@ -631,7 +631,7 @@ class OSPFv3
end
int
end
private
def database_qta(lines)
# DON'T REMOVE THE SPACES!!!

View file

@ -111,3 +111,9 @@ command:/usr/local/opnsense/scripts/quagga/quagga.rb --general-routes6
parameters:
type:script_output
message: Print IPv6 Routing Table
[general-runningconfig]
command:/usr/local/bin/vtysh -c "show run"
parameters:
type:script_output
message: Show running configuration

View file

@ -14,6 +14,11 @@ router bgp {{ OPNsense.quagga.bgp.asnumber }}
network {{ network }}
{% endfor %}
{% endif %}
{% if helpers.exists('OPNsense.quagga.bgp.redistribute') and OPNsense.quagga.bgp.redistribute != '' %}
{% for bgp_redistribute in OPNsense.quagga.bgp.redistribute.split(',') %}
redistribute {{ bgp_redistribute }}
{% endfor %}
{% endif %}
{% if helpers.exists('OPNsense.quagga.bgp.neighbors.neighbor') %}
{% for neighbor in helpers.toList('OPNsense.quagga.bgp.neighbors.neighbor') %}
{% if neighbor.enabled == '1' %}
@ -27,9 +32,77 @@ router bgp {{ OPNsense.quagga.bgp.asnumber }}
{% if 'defaultoriginate' in neighbor and neighbor.defaultoriginate == '1' %}
neighbor {{ neighbor.address }} default-originate
{% endif %}
{% if neighbor.linkedPrefixlistIn|default("") != "" %}
{% for prefixlist in neighbor.linkedPrefixlistIn.split(",") %}
{% set prefixlist2_data = helpers.getUUID(prefixlist) %}
{% if prefixlist2_data != {} and prefixlist2_data.enabled == '1' %}
neighbor {{ neighbor.address }} prefix-list {{ prefixlist2_data.name }} in
{% endif %}
{% endfor %}
{% endif %}
{% if neighbor.linkedPrefixlistOut|default("") != "" %}
{% for prefixlist in neighbor.linkedPrefixlistOut.split(",") %}
{% set prefixlist_data = helpers.getUUID(prefixlist) %}
{% if prefixlist_data != {} and prefixlist_data.enabled == '1' %}
neighbor {{ neighbor.address }} prefix-list {{ prefixlist_data.name }} out
{% endif %}
{% endfor %}
{% endif %}
{% if neighbor.linkedRoutemapIn|default("") != "" %}
{% for aspath in neighbor.linkedRoutemapIn.split(",") %}
{% set routemap2_data = helpers.getUUID(aspath) %}
{% if routemap2_data != {} and routemap2_data.enabled == '1' %}
neighbor {{ neighbor.address }} route-map {{ routemap2_data.name }} in
{% endif %}
{% endfor %}
{% endif %}
{% if neighbor.linkedRoutemapOut|default("") != "" %}
{% for aspath in neighbor.linkedRoutemapOut.split(",") %}
{% set routemap_data = helpers.getUUID(aspath) %}
{% if routemap_data != {} and routemap_data.enabled == '1' %}
neighbor {{ neighbor.address }} route-map {{ routemap_data.name }} out
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
!
{% if helpers.exists('OPNsense.quagga.bgp.prefixlists.prefixlist') %}
{% for prefixlist in helpers.sortDictList(OPNsense.quagga.bgp.prefixlists.prefixlist, 'name', 'seqnumber' ) %}
{% if prefixlist.enabled == '1' %}
ip prefix-list {{ prefixlist.name }} seq {{ prefixlist.seqnumber }} {{ prefixlist.action }} {{ prefixlist.network }}
{% endif %}
{% endfor %}
{% endif %}
!
{% if helpers.exists('OPNsense.quagga.bgp.aspaths.aspath') %}
{% for aspath in helpers.sortDictList(OPNsense.quagga.bgp.aspaths.aspath, 'number' ) %}
{% if aspath.enabled == '1' %}
ip as-path access-list {{ aspath.number }} {{ aspath.action }} {{ aspath.as }}
{% endif %}
{% endfor %}
{% endif %}
!
{% if helpers.exists('OPNsense.quagga.bgp.routemaps.routemap') %}
{% for routemap in helpers.sortDictList(OPNsense.quagga.bgp.routemaps.routemap, 'name', 'id' ) %}
{% if routemap.enabled == '1' %}
route-map {{ routemap.name }} {{ routemap.action }} {{ routemap.id }}
{% if routemap.match|default("") != "" %}
{% for aspath in routemap.match.split(",") %}
{% set aspath_data = helpers.getUUID(aspath) %}
{% if 'match' in routemap and routemap.match != '' %}
match as-path {{ aspath_data.number }}
{% endif %}
{% endfor %}
{% endif %}
{% if routemap.set != '' %}
set {{ routemap.set }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
!
{% endif %}
!
line vty