mirror of
https://github.com/opnsense/plugins.git
synced 2026-06-04 14:26:13 -04:00
net/frr: merge version 0.0.1 from master
This commit is contained in:
parent
6592f43720
commit
e1d89951f3
67 changed files with 23388 additions and 0 deletions
8
net/frr/Makefile
Normal file
8
net/frr/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
PLUGIN_NAME= frr
|
||||
PLUGIN_VERSION= 0.0.1
|
||||
PLUGIN_COMMENT= FRR Routing Suite
|
||||
PLUGIN_DEPENDS= frr ruby
|
||||
PLUGIN_MAINTAINER= franz.fabian.94@gmail.com
|
||||
PLUGIN_DEVEL= YES
|
||||
|
||||
.include "../../Mk/plugins.mk"
|
||||
3
net/frr/pkg-descr
Normal file
3
net/frr/pkg-descr
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
FRRouting (FRR) is an IP routing protocol suite for Linux and Unix platforms
|
||||
which includes protocol daemons for BGP, IS-IS, OSPF and RIP. FRR has its roots
|
||||
in the Quagga project.
|
||||
86
net/frr/src/etc/inc/plugins.inc.d/frr.inc
Normal file
86
net/frr/src/etc/inc/plugins.inc.d/frr.inc
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<?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.
|
||||
*/
|
||||
|
||||
function ospfd_enabled()
|
||||
{
|
||||
$model = new \OPNsense\Quagga\OSPF();
|
||||
if ((string)$model->enabled == '1') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function frr_firewall($fw)
|
||||
{
|
||||
if (ospfd_enabled()) {
|
||||
$ospf = new \OPNsense\Quagga\OSPF();
|
||||
foreach ($ospf->networks->network->__items as $network) {
|
||||
if ((string)$network->enabled == '1') {
|
||||
$fw->registerFilterRule(
|
||||
1, /* priority */
|
||||
array(
|
||||
'ipprotocol' => 'inet',
|
||||
'protocol' => 'ospf',
|
||||
'statetype' => 'keep',
|
||||
'label' => 'Pass OSPF (autogenerated)',
|
||||
'from' => $network->ipaddr . '/' . $network->netmask,
|
||||
'to' => '224.0.0.0/4',
|
||||
'direction' => 'in',
|
||||
'type' => 'pass',
|
||||
'disablereplyto' => 1,
|
||||
'quick' => true
|
||||
),
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function frr_services()
|
||||
{
|
||||
global $config;
|
||||
|
||||
$services = array();
|
||||
|
||||
if (isset($config['OPNsense']['quagga']['general']['enabled']) && $config['OPNsense']['quagga']['general']['enabled'] == 1) {
|
||||
$services[] = array(
|
||||
'description' => gettext('Quagga is a deamon to add support of various routing protocols.'),
|
||||
'configd' => array(
|
||||
'restart' => array('quagga restart'),
|
||||
'start' => array('quagga start'),
|
||||
'stop' => array('quagga stop'),
|
||||
),
|
||||
'name' => 'quagga',
|
||||
'pidfile' => '/var/run/quagga/zebra.pid'
|
||||
);
|
||||
}
|
||||
|
||||
return $services;
|
||||
}
|
||||
|
|
@ -0,0 +1,506 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (C) 2015 - 2017 Deciso B.V.
|
||||
* Copyright (C) 2017 Fabian Franz
|
||||
* Copyright (C) 2017 Michael Muenz
|
||||
*
|
||||
* 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\Quagga\BGP;
|
||||
use \OPNsense\Core\Config;
|
||||
use \OPNsense\Base\ApiMutableModelControllerBase;
|
||||
use \OPNsense\Base\UIModelGrid;
|
||||
|
||||
class BgpController extends ApiMutableModelControllerBase
|
||||
{
|
||||
static protected $internalModelName = 'BGP';
|
||||
static protected $internalModelClass = '\OPNsense\Quagga\BGP';
|
||||
public function getAction()
|
||||
{
|
||||
// define list of configurable settings
|
||||
$result = array();
|
||||
if ($this->request->isGet()) {
|
||||
$mdlBGP = new BGP();
|
||||
$result['bgp'] = $mdlBGP->getNodes();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function setAction()
|
||||
{
|
||||
$result = array("result"=>"failed");
|
||||
if ($this->request->isPost()) {
|
||||
// load model and update with provided data
|
||||
$mdlBGP = new BGP();
|
||||
$mdlBGP->setNodes($this->request->getPost("bgp"));
|
||||
// perform validation
|
||||
$valMsgs = $mdlBGP->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
if (!array_key_exists("validations", $result)) {
|
||||
$result["validations"] = array();
|
||||
}
|
||||
$result["validations"]["bgp.".$msg->getField()] = $msg->getMessage();
|
||||
}
|
||||
// serialize model to config and save
|
||||
if ($valMsgs->count() == 0) {
|
||||
$mdlBGP->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function searchNeighborAction()
|
||||
{
|
||||
$this->sessionClose();
|
||||
$mdlBGP = $this->getModel();
|
||||
$grid = new UIModelGrid($mdlBGP->neighbors->neighbor);
|
||||
return $grid->fetchBindRequest(
|
||||
$this->request,
|
||||
array("enabled", "address", "remoteas", "updatesource", "nexthopself", "defaultoriginate", "linkedPrefixlistIn", "linkedPrefixlistOut", "linkedRoutemapIn", "linkedRoutemapOut" )
|
||||
);
|
||||
}
|
||||
|
||||
public function getNeighborAction($uuid = null)
|
||||
{
|
||||
$mdlBGP = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlBGP->getNodeByReference('neighbors.neighbor.' . $uuid);
|
||||
if ($node != null) {
|
||||
// return node
|
||||
return array("neighbor" => $node->getNodes());
|
||||
}
|
||||
} else {
|
||||
$node = $mdlBGP->neighbors->neighbor->add();
|
||||
return array("neighbor" => $node->getNodes());
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
public function addNeighborAction()
|
||||
{
|
||||
$result = array("result" => "failed");
|
||||
if ($this->request->isPost() && $this->request->hasPost("neighbor")) {
|
||||
$result = array("result" => "failed", "validations" => array());
|
||||
$mdlBGP = $this->getModel();
|
||||
$node = $mdlBGP->neighbors->neighbor->Add();
|
||||
$node->setNodes($this->request->getPost("neighbor"));
|
||||
$valMsgs = $mdlBGP->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
$fieldnm = str_replace($node->__reference, "neighbor", $msg->getField());
|
||||
$result["validations"][$fieldnm] = $msg->getMessage();
|
||||
}
|
||||
if (count($result['validations']) == 0) {
|
||||
unset($result['validations']);
|
||||
// save config if validated correctly
|
||||
$mdlBGP->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
unset($result['validations']);
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function delNeighborAction($uuid)
|
||||
{
|
||||
$result = array("result" => "failed");
|
||||
if ($this->request->isPost()) {
|
||||
$mdlBGP = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
if ($mdlBGP->neighbors->neighbor->del($uuid)) {
|
||||
$mdlBGP->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result['result'] = 'deleted';
|
||||
} else {
|
||||
$result['result'] = 'not found';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setNeighborAction($uuid)
|
||||
{
|
||||
if ($this->request->isPost() && $this->request->hasPost("neighbor")) {
|
||||
$mdlNeighbor = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlNeighbor->getNodeByReference('neighbors.neighbor.' . $uuid);
|
||||
if ($node != null) {
|
||||
$result = array("result" => "failed", "validations" => array());
|
||||
$neighborInfo = $this->request->getPost("neighbor");
|
||||
$node->setNodes($neighborInfo);
|
||||
$valMsgs = $mdlNeighbor->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
$fieldnm = str_replace($node->__reference, "neighbor", $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 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");
|
||||
if ($this->request->isPost()) {
|
||||
$mdlNeighbor = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlNeighbor->getNodeByReference($elements . '.'. $element .'.' . $uuid);
|
||||
if ($node != null) {
|
||||
if ($node->enabled->__toString() == "1") {
|
||||
$result['result'] = "Disabled";
|
||||
$node->enabled = "0";
|
||||
} else {
|
||||
$result['result'] = "Enabled";
|
||||
$node->enabled = "1";
|
||||
}
|
||||
// if item has toggled, serialize to config and save
|
||||
$mdlNeighbor->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function toggleNeighborAction($uuid)
|
||||
{
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (C) 2017 Frank Wall
|
||||
* Copyright (C) 2017 Michael Muenz
|
||||
*
|
||||
* 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\ApiControllerBase;
|
||||
use \OPNsense\Core\Backend;
|
||||
use \OPNsense\Core\Config;
|
||||
|
||||
/**
|
||||
* Class DiagnosticsController
|
||||
* @package OPNsense\Quagga
|
||||
*/
|
||||
class DiagnosticsController extends ApiControllerBase
|
||||
{
|
||||
/**
|
||||
* show ip bgp
|
||||
* @return array
|
||||
*/
|
||||
public function showipbgpAction()
|
||||
{
|
||||
$backend = new Backend();
|
||||
$response = json_decode(trim($backend->configdRun("quagga diag-bgp2")));
|
||||
return array("response" => $response);
|
||||
}
|
||||
/**
|
||||
* show ip bgp summary
|
||||
* @return array
|
||||
*/
|
||||
public function showipbgpsummaryAction()
|
||||
{
|
||||
$backend = new Backend();
|
||||
$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();
|
||||
return array("response" => json_decode(trim($backend->configdRun("quagga ospf-$name"))));
|
||||
}
|
||||
private function get_ospf3_information($name)
|
||||
{
|
||||
$backend = new Backend();
|
||||
return array("response" => json_decode(trim($backend->configdRun("quagga ospfv3-$name"))));
|
||||
}
|
||||
// OSPFv2
|
||||
public function ospfoverviewAction()
|
||||
{
|
||||
return $this->get_ospf_information('overview');
|
||||
}
|
||||
public function ospfneighborAction()
|
||||
{
|
||||
return $this->get_ospf_information('neighbor');
|
||||
}
|
||||
public function ospfrouteAction()
|
||||
{
|
||||
return $this->get_ospf_information('route');
|
||||
}
|
||||
public function ospfdatabaseAction()
|
||||
{
|
||||
return $this->get_ospf_information('database');
|
||||
}
|
||||
public function ospfinterfaceAction()
|
||||
{
|
||||
return $this->get_ospf_information('interface');
|
||||
}
|
||||
// OSPFv3
|
||||
public function ospfv3overviewAction()
|
||||
{
|
||||
return $this->get_ospf3_information('overview');
|
||||
}
|
||||
public function ospfv3neighborAction()
|
||||
{
|
||||
return $this->get_ospf3_information('neighbor');
|
||||
}
|
||||
public function ospfv3routeAction()
|
||||
{
|
||||
return $this->get_ospf3_information('route');
|
||||
}
|
||||
public function ospfv3databaseAction()
|
||||
{
|
||||
return $this->get_ospf3_information('database');
|
||||
}
|
||||
public function ospfv3interfaceAction()
|
||||
{
|
||||
return $this->get_ospf3_information('interface');
|
||||
}
|
||||
// General
|
||||
private function get_general_information($name)
|
||||
{
|
||||
$backend = new Backend();
|
||||
return array("response" => json_decode(trim($backend->configdRun("quagga general-$name")), true));
|
||||
}
|
||||
public function generalroutesAction()
|
||||
{
|
||||
return $this->get_general_information('routes');
|
||||
}
|
||||
public function logAction()
|
||||
{
|
||||
return $this->get_general_information('log')['response']['general_log'];
|
||||
}
|
||||
public function generalroutes6Action()
|
||||
{
|
||||
return $this->get_general_information('routes6');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (C) 2015 - 2017 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 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\ApiControllerBase;
|
||||
use \OPNsense\Quagga\General;
|
||||
use \OPNsense\Core\Config;
|
||||
|
||||
class GeneralController extends ApiControllerBase
|
||||
{
|
||||
public function getAction()
|
||||
{
|
||||
// define list of configurable settings
|
||||
$result = array();
|
||||
if ($this->request->isGet()) {
|
||||
$mdlGeneral = new General();
|
||||
$result['general'] = $mdlGeneral->getNodes();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function setAction()
|
||||
{
|
||||
$result = array("result"=>"failed");
|
||||
if ($this->request->isPost()) {
|
||||
// load model and update with provided data
|
||||
$mdlGeneral = new General();
|
||||
$mdlGeneral->setNodes($this->request->getPost("general"));
|
||||
|
||||
// perform validation
|
||||
$valMsgs = $mdlGeneral->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
if (!array_key_exists("validations", $result)) {
|
||||
$result["validations"] = array();
|
||||
}
|
||||
$result["validations"]["general.".$msg->getField()] = $msg->getMessage();
|
||||
}
|
||||
|
||||
// serialize model to config and save
|
||||
if ($valMsgs->count() == 0) {
|
||||
$mdlGeneral->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Deciso B.V.
|
||||
* Copyright (C) 2015 Jos Schellevis
|
||||
* Copyright (C) 2017 Fabian Franz
|
||||
* Copyright (C) 2017 Michael Muenz
|
||||
* 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\Quagga\OSPF6;
|
||||
use \OPNsense\Core\Config;
|
||||
use \OPNsense\Base\ApiMutableModelControllerBase;
|
||||
use \OPNsense\Base\UIModelGrid;
|
||||
|
||||
class Ospf6settingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
static protected $internalModelName = 'OSPF6';
|
||||
static protected $internalModelClass = '\OPNsense\Quagga\OSPF6';
|
||||
public function getAction()
|
||||
{
|
||||
$result = array();
|
||||
if ($this->request->isGet()) {
|
||||
$mdlospf6 = new OSPF6();
|
||||
$result['ospf6'] = $mdlospf6->getNodes();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function setAction()
|
||||
{
|
||||
$result = array("result"=>"failed");
|
||||
if ($this->request->isPost()) {
|
||||
// load model and update with provided data
|
||||
$mdlospf6 = new OSPF6();
|
||||
$mdlospf6->setNodes($this->request->getPost("ospf6"));
|
||||
// perform validation
|
||||
$valMsgs = $mdlospf6->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
if (!array_key_exists("validations", $result)) {
|
||||
$result["validations"] = array();
|
||||
}
|
||||
$result["validations"]["general.".$msg->getField()] = $msg->getMessage();
|
||||
}
|
||||
// serialize model to config and save
|
||||
if ($valMsgs->count() == 0) {
|
||||
$mdlospf6->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
public function searchInterfaceAction()
|
||||
{
|
||||
$this->sessionClose();
|
||||
$mdlOSPF6 = $this->getModel();
|
||||
$grid = new UIModelGrid($mdlOSPF6->interfaces->interface);
|
||||
return $grid->fetchBindRequest(
|
||||
$this->request,
|
||||
array("enabled", "interfacename", "area", "networktype")
|
||||
);
|
||||
}
|
||||
public function getInterfaceAction($uuid = null)
|
||||
{
|
||||
$mdlOSPF6 = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlOSPF6->getNodeByReference('interfaces.interface.' . $uuid);
|
||||
if ($node != null) {
|
||||
// return node
|
||||
return array("interface" => $node->getNodes());
|
||||
}
|
||||
} else {
|
||||
$node = $mdlOSPF6->interfaces->interface->add();
|
||||
return array("interface" => $node->getNodes());
|
||||
}
|
||||
return array();
|
||||
}
|
||||
public function addInterfaceAction()
|
||||
{
|
||||
$result = array("result" => "failed");
|
||||
if ($this->request->isPost() && $this->request->hasPost("interface")) {
|
||||
$result = array("result" => "failed", "validations" => array());
|
||||
$mdlOSPF6 = $this->getModel();
|
||||
$node = $mdlOSPF6->interfaces->interface->Add();
|
||||
$node->setNodes($this->request->getPost("interface"));
|
||||
$valMsgs = $mdlOSPF6->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
$fieldnm = str_replace($node->__reference, "interface", $msg->getField());
|
||||
$result["validations"][$fieldnm] = $msg->getMessage();
|
||||
}
|
||||
if (count($result['validations']) == 0) {
|
||||
// save config if validated correctly
|
||||
$mdlOSPF6->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
unset($result['validations']);
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function delInterfaceAction($uuid)
|
||||
{
|
||||
$result = array("result" => "failed");
|
||||
if ($this->request->isPost()) {
|
||||
$mdlOSPF6 = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
if ($mdlOSPF6->interfaces->interface->del($uuid)) {
|
||||
$mdlOSPF6->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result['result'] = 'deleted';
|
||||
} else {
|
||||
$result['result'] = 'not found';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function setInterfaceAction($uuid)
|
||||
{
|
||||
if ($this->request->isPost() && $this->request->hasPost("interface")) {
|
||||
$mdlNetwork = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlNetwork->getNodeByReference('interfaces.interface.' . $uuid);
|
||||
if ($node != null) {
|
||||
$result = array("result" => "failed", "validations" => array());
|
||||
$interfaceInfo = $this->request->getPost("interface");
|
||||
$node->setNodes($interfaceInfo);
|
||||
$valMsgs = $mdlNetwork->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
$fieldnm = str_replace($node->__reference, "interface", $msg->getField());
|
||||
$result["validations"][$fieldnm] = $msg->getMessage();
|
||||
}
|
||||
if (count($result['validations']) == 0) {
|
||||
// save config if validated correctly
|
||||
$mdlNetwork->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");
|
||||
if ($this->request->isPost()) {
|
||||
$mdlNetwork = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlNetwork->getNodeByReference($elements . '.'. $element .'.' . $uuid);
|
||||
if ($node != null) {
|
||||
if ($node->enabled->__toString() == "1") {
|
||||
$result['result'] = "Disabled";
|
||||
$node->enabled = "0";
|
||||
} else {
|
||||
$result['result'] = "Enabled";
|
||||
$node->enabled = "1";
|
||||
}
|
||||
// if item has toggled, serialize to config and save
|
||||
$mdlNetwork->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function toggleInterfaceAction($uuid)
|
||||
{
|
||||
return $this->toggle_handler($uuid, 'interfaces', 'interface');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Deciso B.V.
|
||||
* Copyright (C) 2015 Jos Schellevis
|
||||
* 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\Api;
|
||||
|
||||
use \OPNsense\Quagga\OSPF;
|
||||
use \OPNsense\Core\Config;
|
||||
use \OPNsense\Base\ApiMutableModelControllerBase;
|
||||
use \OPNsense\Base\UIModelGrid;
|
||||
|
||||
class OspfsettingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
static protected $internalModelName = 'OSPF';
|
||||
static protected $internalModelClass = '\OPNsense\Quagga\OSPF';
|
||||
public function getAction()
|
||||
{
|
||||
$result = array();
|
||||
if ($this->request->isGet()) {
|
||||
$mdlospf = new OSPF();
|
||||
$result['ospf'] = $mdlospf->getNodes();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setAction()
|
||||
{
|
||||
$result = array("result"=>"failed");
|
||||
if ($this->request->isPost()) {
|
||||
// load model and update with provided data
|
||||
$mdlospf = new OSPF();
|
||||
$mdlospf->setNodes($this->request->getPost("ospf"));
|
||||
|
||||
// perform validation
|
||||
$valMsgs = $mdlospf->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
if (!array_key_exists("validations", $result)) {
|
||||
$result["validations"] = array();
|
||||
}
|
||||
$result["validations"]["general.".$msg->getField()] = $msg->getMessage();
|
||||
}
|
||||
|
||||
// serialize model to config and save
|
||||
if ($valMsgs->count() == 0) {
|
||||
$mdlospf->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
public function searchNetworkAction()
|
||||
{
|
||||
$this->sessionClose();
|
||||
$mdlOSPF = $this->getModel();
|
||||
$grid = new UIModelGrid($mdlOSPF->networks->network);
|
||||
return $grid->fetchBindRequest(
|
||||
$this->request,
|
||||
array("enabled", "ipaddr", "netmask", "area")
|
||||
);
|
||||
}
|
||||
public function searchInterfaceAction()
|
||||
{
|
||||
$this->sessionClose();
|
||||
$mdlOSPF = $this->getModel();
|
||||
$grid = new UIModelGrid($mdlOSPF->interfaces->interface);
|
||||
return $grid->fetchBindRequest(
|
||||
$this->request,
|
||||
array("enabled", "interfacename", "networktype", "authtype", "area")
|
||||
);
|
||||
}
|
||||
public function searchPrefixlistAction()
|
||||
{
|
||||
$this->sessionClose();
|
||||
$mdlOSPF = $this->getModel();
|
||||
$grid = new UIModelGrid($mdlOSPF->prefixlists->prefixlist);
|
||||
return $grid->fetchBindRequest(
|
||||
$this->request,
|
||||
array("enabled", "name", "seqnumber", "action", "network" )
|
||||
);
|
||||
}
|
||||
public function getNetworkAction($uuid = null)
|
||||
{
|
||||
$mdlOSPF = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlOSPF->getNodeByReference('networks.network.' . $uuid);
|
||||
if ($node != null) {
|
||||
// return node
|
||||
return array("network" => $node->getNodes());
|
||||
}
|
||||
} else {
|
||||
$node = $mdlOSPF->networks->network->add();
|
||||
return array("network" => $node->getNodes());
|
||||
}
|
||||
return array();
|
||||
}
|
||||
public function getInterfaceAction($uuid = null)
|
||||
{
|
||||
$mdlOSPF = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlOSPF->getNodeByReference('interfaces.interface.' . $uuid);
|
||||
if ($node != null) {
|
||||
// return node
|
||||
return array("interface" => $node->getNodes());
|
||||
}
|
||||
} else {
|
||||
$node = $mdlOSPF->interfaces->interface->add();
|
||||
return array("interface" => $node->getNodes());
|
||||
}
|
||||
return array();
|
||||
}
|
||||
public function getPrefixlistAction($uuid = null)
|
||||
{
|
||||
$mdlOSPF = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlOSPF->getNodeByReference('prefixlists.prefixlist.' . $uuid);
|
||||
if ($node != null) {
|
||||
// return node
|
||||
return array("prefixlist" => $node->getNodes());
|
||||
}
|
||||
} else {
|
||||
$node = $mdlOSPF->prefixlists->prefixlist->add();
|
||||
return array("prefixlist" => $node->getNodes());
|
||||
}
|
||||
return array();
|
||||
}
|
||||
public function addNetworkAction()
|
||||
{
|
||||
$result = array("result" => "failed");
|
||||
if ($this->request->isPost() && $this->request->hasPost("network")) {
|
||||
$result = array("result" => "failed", "validations" => array());
|
||||
$mdlOSPF = $this->getModel();
|
||||
$node = $mdlOSPF->networks->network->Add();
|
||||
$node->setNodes($this->request->getPost("network"));
|
||||
$valMsgs = $mdlOSPF->performValidation();
|
||||
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
$fieldnm = str_replace($node->__reference, "network", $msg->getField());
|
||||
$result["validations"][$fieldnm] = $msg->getMessage();
|
||||
}
|
||||
|
||||
if (count($result['validations']) == 0) {
|
||||
// save config if validated correctly
|
||||
$mdlOSPF->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
unset($result['validations']);
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function addInterfaceAction()
|
||||
{
|
||||
$result = array("result" => "failed");
|
||||
if ($this->request->isPost() && $this->request->hasPost("interface")) {
|
||||
$result = array("result" => "failed", "validations" => array());
|
||||
$mdlOSPF = $this->getModel();
|
||||
$node = $mdlOSPF->interfaces->interface->Add();
|
||||
$node->setNodes($this->request->getPost("interface"));
|
||||
$valMsgs = $mdlOSPF->performValidation();
|
||||
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
$fieldnm = str_replace($node->__reference, "interface", $msg->getField());
|
||||
$result["validations"][$fieldnm] = $msg->getMessage();
|
||||
}
|
||||
|
||||
if (count($result['validations']) == 0) {
|
||||
// save config if validated correctly
|
||||
$mdlOSPF->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
unset($result['validations']);
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function addPrefixlistAction()
|
||||
{
|
||||
$result = array("result" => "failed");
|
||||
if ($this->request->isPost() && $this->request->hasPost("prefixlist")) {
|
||||
$result = array("result" => "failed", "validations" => array());
|
||||
$mdlOSPF = $this->getModel();
|
||||
$node = $mdlOSPF->prefixlists->prefixlist->Add();
|
||||
$node->setNodes($this->request->getPost("prefixlist"));
|
||||
$valMsgs = $mdlOSPF->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
|
||||
$mdlOSPF->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
unset($result['validations']);
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function delNetworkAction($uuid)
|
||||
{
|
||||
|
||||
$result = array("result" => "failed");
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$mdlOSPF = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
if ($mdlOSPF->networks->network->del($uuid)) {
|
||||
$mdlOSPF->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result['result'] = 'deleted';
|
||||
} else {
|
||||
$result['result'] = 'not found';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function delInterfaceAction($uuid)
|
||||
{
|
||||
|
||||
$result = array("result" => "failed");
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$mdlOSPF = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
if ($mdlOSPF->interfaces->interface->del($uuid)) {
|
||||
$mdlOSPF->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result['result'] = 'deleted';
|
||||
} else {
|
||||
$result['result'] = 'not found';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function delPrefixlistAction($uuid)
|
||||
{
|
||||
$result = array("result" => "failed");
|
||||
if ($this->request->isPost()) {
|
||||
$mdlOSPF = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
if ($mdlOSPF->prefixlists->prefixlist->del($uuid)) {
|
||||
$mdlOSPF->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result['result'] = 'deleted';
|
||||
} else {
|
||||
$result['result'] = 'not found';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function setNetworkAction($uuid)
|
||||
{
|
||||
if ($this->request->isPost() && $this->request->hasPost("network")) {
|
||||
$mdlNetwork = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlNetwork->getNodeByReference('networks.network.' . $uuid);
|
||||
if ($node != null) {
|
||||
$result = array("result" => "failed", "validations" => array());
|
||||
$networkInfo = $this->request->getPost("network");
|
||||
|
||||
$node->setNodes($networkInfo);
|
||||
$valMsgs = $mdlNetwork->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
$fieldnm = str_replace($node->__reference, "network", $msg->getField());
|
||||
$result["validations"][$fieldnm] = $msg->getMessage();
|
||||
}
|
||||
|
||||
if (count($result['validations']) == 0) {
|
||||
// save config if validated correctly
|
||||
$mdlNetwork->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result = array("result" => "saved");
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array("result" => "failed");
|
||||
}
|
||||
public function setInterfaceAction($uuid)
|
||||
{
|
||||
if ($this->request->isPost() && $this->request->hasPost("interface")) {
|
||||
$mdlNetwork = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlNetwork->getNodeByReference('interfaces.interface.' . $uuid);
|
||||
if ($node != null) {
|
||||
$result = array("result" => "failed", "validations" => array());
|
||||
$interfaceInfo = $this->request->getPost("interface");
|
||||
|
||||
$node->setNodes($interfaceInfo);
|
||||
$valMsgs = $mdlNetwork->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
$fieldnm = str_replace($node->__reference, "interface", $msg->getField());
|
||||
$result["validations"][$fieldnm] = $msg->getMessage();
|
||||
}
|
||||
|
||||
if (count($result['validations']) == 0) {
|
||||
// save config if validated correctly
|
||||
$mdlNetwork->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result = array("result" => "saved");
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array("result" => "failed");
|
||||
}
|
||||
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 toggle_handler($uuid, $elements, $element)
|
||||
{
|
||||
|
||||
$result = array("result" => "failed");
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$mdlNetwork = $this->getModel();
|
||||
if ($uuid != null) {
|
||||
$node = $mdlNetwork->getNodeByReference($elements . '.'. $element .'.' . $uuid);
|
||||
if ($node != null) {
|
||||
if ($node->enabled->__toString() == "1") {
|
||||
$result['result'] = "Disabled";
|
||||
$node->enabled = "0";
|
||||
} else {
|
||||
$result['result'] = "Enabled";
|
||||
$node->enabled = "1";
|
||||
}
|
||||
// if item has toggled, serialize to config and save
|
||||
$mdlNetwork->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function toggleNetworkAction($uuid)
|
||||
{
|
||||
return $this->toggle_handler($uuid, 'networks', 'network');
|
||||
}
|
||||
public function toggleInterfaceAction($uuid)
|
||||
{
|
||||
return $this->toggle_handler($uuid, 'interfaces', 'interface');
|
||||
}
|
||||
public function togglePrefixlistAction($uuid)
|
||||
{
|
||||
return $this->toggle_handler($uuid, 'prefixlists', 'prefixlist');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (C) 2015 - 2017 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 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\ApiControllerBase;
|
||||
use \OPNsense\Quagga\RIP;
|
||||
use \OPNsense\Core\Config;
|
||||
|
||||
class RipController extends ApiControllerBase
|
||||
{
|
||||
public function getAction()
|
||||
{
|
||||
// define list of configurable settings
|
||||
$result = array();
|
||||
if ($this->request->isGet()) {
|
||||
$mdlRIP = new RIP();
|
||||
$result['rip'] = $mdlRIP->getNodes();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function setAction()
|
||||
{
|
||||
$result = array("result"=>"failed");
|
||||
if ($this->request->isPost()) {
|
||||
// load model and update with provided data
|
||||
$mdlRIP = new RIP();
|
||||
$mdlRIP->setNodes($this->request->getPost("rip"));
|
||||
|
||||
// perform validation
|
||||
$valMsgs = $mdlRIP->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
if (!array_key_exists("validations", $result)) {
|
||||
$result["validations"] = array();
|
||||
}
|
||||
$result["validations"]["rip.".$msg->getField()] = $msg->getMessage();
|
||||
}
|
||||
|
||||
// serialize model to config and save
|
||||
if ($valMsgs->count() == 0) {
|
||||
$mdlRIP->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (C) 2015 - 2017 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 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\ApiControllerBase;
|
||||
use \OPNsense\Core\Backend;
|
||||
use \OPNsense\Quagga\General;
|
||||
|
||||
/**
|
||||
* Class ServiceController
|
||||
* @package OPNsense\Quagga
|
||||
*/
|
||||
class ServiceController extends ApiControllerBase
|
||||
{
|
||||
/**
|
||||
* start quagga service and reload filter rules to pass OSPF
|
||||
* before the bogon filter kills the routing protocol packets
|
||||
* @return array
|
||||
*/
|
||||
public function startAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$backend = new Backend();
|
||||
$response = $backend->configdRun('quagga start');
|
||||
$backend->configdRun('filter reload');
|
||||
return array('response' => $response);
|
||||
} else {
|
||||
return array('response' => array());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stop quagga service
|
||||
* @return array
|
||||
*/
|
||||
public function stopAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$backend = new Backend();
|
||||
$response = $backend->configdRun('quagga stop');
|
||||
return array('response' => $response);
|
||||
} else {
|
||||
return array('response' => array());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* restart quagga service
|
||||
* @return array
|
||||
*/
|
||||
public function restartAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$backend = new Backend();
|
||||
$response = $backend->configdRun('quagga restart');
|
||||
$backend->configdRun('filter reload');
|
||||
return array('response' => $response);
|
||||
} else {
|
||||
return array('response' => array());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve status of quagga
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function statusAction()
|
||||
{
|
||||
$backend = new Backend();
|
||||
$mdlGeneral = new General();
|
||||
$response = $backend->configdRun('quagga status');
|
||||
|
||||
if (strpos($response, 'not running') > 0) {
|
||||
if ($mdlGeneral->enabled->__toString() == 1) {
|
||||
$status = 'stopped';
|
||||
} else {
|
||||
$status = 'disabled';
|
||||
}
|
||||
} elseif (strpos($response, 'is running') > 0) {
|
||||
$status = 'running';
|
||||
} elseif ($mdlGeneral->enabled->__toString() == 0) {
|
||||
$status = 'disabled';
|
||||
} else {
|
||||
$status = 'unknown';
|
||||
}
|
||||
|
||||
|
||||
return array('status' => $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* reconfigure quagga, generate config and reload
|
||||
*/
|
||||
public function reconfigureAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
// close session for long running action
|
||||
$this->sessionClose();
|
||||
|
||||
$mdlGeneral = new General();
|
||||
$backend = new Backend();
|
||||
|
||||
$runStatus = $this->statusAction();
|
||||
|
||||
// stop quagga if it is running or not
|
||||
$this->stopAction();
|
||||
|
||||
// generate template
|
||||
$backend->configdRun('template reload OPNsense/Quagga');
|
||||
|
||||
// (res)start daemon
|
||||
if ($mdlGeneral->enabled->__toString() == 1) {
|
||||
$this->startAction();
|
||||
}
|
||||
|
||||
return array('status' => 'ok');
|
||||
} else {
|
||||
return array('status' => 'failed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/*
|
||||
Copyright (C) 2017 Fabian Franz
|
||||
Copyright (C) 2017 Michael Muenz
|
||||
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 BgpController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$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');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/*
|
||||
Copyright (C) 2017 Fabian Franz
|
||||
Copyright (C) 2017 Michael Muenz
|
||||
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 DiagnosticsController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function bgpAction()
|
||||
{
|
||||
$this->view->title = gettext("Diagnostics: BGP");
|
||||
$this->view->diagnosticsForm = $this->getForm("diagnostics");
|
||||
$this->view->pick('OPNsense/Quagga/diagnosticsbgp');
|
||||
}
|
||||
public function ospfAction()
|
||||
{
|
||||
$this->view->title = gettext("Diagnostics: OSPF");
|
||||
$this->view->pick('OPNsense/Quagga/diagnosticsospf');
|
||||
}
|
||||
public function ospfv3Action()
|
||||
{
|
||||
$this->view->title = gettext("Diagnostics: OSPFv3");
|
||||
$this->view->pick('OPNsense/Quagga/diagnosticsospfv3');
|
||||
}
|
||||
public function generalAction()
|
||||
{
|
||||
$this->view->title = gettext("Diagnostics: General");
|
||||
$this->view->pick('OPNsense/Quagga/diagnosticsgeneral');
|
||||
}
|
||||
public function logAction()
|
||||
{
|
||||
$this->view->title = gettext("Diagnostics: Log");
|
||||
$this->view->pick('OPNsense/Quagga/log');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?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 GeneralController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->title = gettext("Routing-Settings");
|
||||
$this->view->generalForm = $this->getForm("general");
|
||||
$this->view->pick('OPNsense/Quagga/general');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?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
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->title = gettext("IS-IS-Settings");
|
||||
$this->view->generalForm = $this->getForm("isis");
|
||||
$this->view->pick('OPNsense/Quagga/isis');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
/*
|
||||
Copyright (C) 2017 Fabian Franz
|
||||
Copyright (C) 2017 Michael Muenz
|
||||
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 Ospf6Controller extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->title = gettext("OSPFv3 Settings");
|
||||
$this->view->ospf6Form = $this->getForm("ospf6");
|
||||
$this->view->formDialogEditInterface = $this->getForm("dialogEditOSPF6Interface");
|
||||
$this->view->pick('OPNsense/Quagga/ospf6');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?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 OspfController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->title = gettext("OSPF Settings");
|
||||
$this->view->generalForm = $this->getForm("ospf");
|
||||
$this->view->formDialogEditNetwork = $this->getForm("dialogEditOSPFNetwork");
|
||||
$this->view->formDialogEditInterface = $this->getForm("dialogEditOSPFInterface");
|
||||
$this->view->formDialogEditPrefixLists = $this->getForm("dialogEditOSPFPrefixLists");
|
||||
$this->view->pick('OPNsense/Quagga/ospf');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?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
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->title = gettext("RIP Settings");
|
||||
$this->view->ripForm = $this->getForm("rip");
|
||||
$this->view->pick('OPNsense/Quagga/rip');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>bgp.enabled</id>
|
||||
<label>enable</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will activate the bgp service.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>bgp.asnumber</id>
|
||||
<label>BGP AS Number</label>
|
||||
<type>text</type>
|
||||
<help>Your AS Number here</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>bgp.networks</id>
|
||||
<label>Network</label>
|
||||
<style>tokenize</style>
|
||||
<type>select_multiple</type>
|
||||
<allownew>true</allownew>
|
||||
<help>Select the network to advertise, you have to set a Null route via System -> Routes</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>bgp.redistribute</id>
|
||||
<label>Route Redistribution</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<help><![CDATA[Select other routing sources, which should be redistributed to the other nodes.]]></help>
|
||||
<hint>Type or select a route source.</hint>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>diagnostics.bgpneighbor</id>
|
||||
<label>BGP Neighbor</label>
|
||||
<type>text</type>
|
||||
<hint>One of the neighbor IPs</hint>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>neighbor.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>neighbor.address</id>
|
||||
<label>Peer-IP</label>
|
||||
<type>text</type>
|
||||
<help>Specify the IP of your neighbor.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>neighbor.remoteas</id>
|
||||
<label>Remote AS</label>
|
||||
<type>text</type>
|
||||
<help>Neighbor AS.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>neighbor.updatesource</id>
|
||||
<label>Update-Source Interface</label>
|
||||
<type>select_multiple</type>
|
||||
<help>Physical name of the interface facing the peer</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>neighbor.nexthopself</id>
|
||||
<label>Next-Hop-Self</label>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>neighbor.defaultoriginate</id>
|
||||
<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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>interface.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.interfacename</id>
|
||||
<label>Interface</label>
|
||||
<style>tokenize</style>
|
||||
<type>select_multiple</type>
|
||||
<help>Select an interface where this settings apply to.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.area</id>
|
||||
<label>Area</label>
|
||||
<type>text</type>
|
||||
<help>Area in wildcard mask style like 0.0.0.0 and no decimal 0</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.cost</id>
|
||||
<label>Cost</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.hellointerval</id>
|
||||
<label>Hello Interval</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.deadinterval</id>
|
||||
<label>Dead Interval</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.retransmitinterval</id>
|
||||
<label>Retransmission Interval</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.transmitdelay</id>
|
||||
<label>Retransmission Delay</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.priority</id>
|
||||
<label>Priority</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.networktype</id>
|
||||
<label>Network Type</label>
|
||||
<type>select_multiple</type>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>interface.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.interfacename</id>
|
||||
<label>Interface</label>
|
||||
<style>tokenize</style>
|
||||
<type>select_multiple</type>
|
||||
<help>Select an interface where this settings apply to.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.authtype</id>
|
||||
<label>Authentication Type</label>
|
||||
<type>select_multiple</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.authkey</id>
|
||||
<label>Authentication Key</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.cost</id>
|
||||
<label>Cost</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.hellointerval</id>
|
||||
<label>Hello Interval</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.deadinterval</id>
|
||||
<label>Dead Interval</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.retransmitinterval</id>
|
||||
<label>Retransmission Interval</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.transmitdelay</id>
|
||||
<label>Retransmission Delay</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.priority</id>
|
||||
<label>Priority</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>interface.networktype</id>
|
||||
<label>Network Type</label>
|
||||
<type>select_multiple</type>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>network.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>network.ipaddr</id>
|
||||
<label>Network Address</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>network.netmask</id>
|
||||
<label>Network Mask</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>network.area</id>
|
||||
<label>Area</label>
|
||||
<type>text</type>
|
||||
<help>Area in wildcard mask style like 0.0.0.0 and no decimal 0</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>network.linkedPrefixlistIn</id>
|
||||
<label>Prefix-List In</label>
|
||||
<type>dropdown</type>
|
||||
<help>Prefix-List for inbound direction</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>network.linkedPrefixlistOut</id>
|
||||
<label>Prefix-List Out</label>
|
||||
<type>dropdown</type>
|
||||
<help>Prefix-List for outbound direction</help>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -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. It's not validated so please be careful!</help>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>general.enabled</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will activate the routing service.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>general.enablelogfile</id>
|
||||
<label>Create a logfile</label>
|
||||
<type>checkbox</type>
|
||||
<help>If you check this, a log file will be written to disk.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>general.logfilelevel</id>
|
||||
<label>Logfile level</label>
|
||||
<type>dropdown</type>
|
||||
<help>This is the detail level of the log. A higher level means more data is logged.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>general.enablesyslog</id>
|
||||
<label>Send log messages to syslog</label>
|
||||
<type>checkbox</type>
|
||||
<help>Syslog is a service which is made to collect log messages from different software and maybe to a central logging server. Check this box if you have such a setup.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>general.sysloglevel</id>
|
||||
<label>Syslog level</label>
|
||||
<type>dropdown</type>
|
||||
<help>This is the detail level of the log. A higher level means more data is logged.</help>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>routing.isis.general.Enabled</id>
|
||||
<label>enable</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will activate the isis service.</help>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>ospf.enabled</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will activate the OSPF service if routing protocols are enabled in "General".</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>ospf.routerid</id>
|
||||
<label>Router ID</label>
|
||||
<type>text</type>
|
||||
<advanced>true</advanced>
|
||||
<help>If you have a CARP setup, you may want to configure a router id in case of a conflict.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>ospf.passiveinterfaces</id>
|
||||
<label>Passive Interfaces</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<help><![CDATA[Select the interfaces, where no OSPF packets should be sent to.]]></help>
|
||||
<hint>Type or select interface.</hint>
|
||||
</field>
|
||||
<field>
|
||||
<id>ospf.redistribute</id>
|
||||
<label>Route Redistribution</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<help><![CDATA[Select other routing sources, which should be redistributed to the other nodes.]]></help>
|
||||
<hint>Type or select a route source.</hint>
|
||||
</field>
|
||||
<field>
|
||||
<id>ospf.originate</id>
|
||||
<label>Advertise Default Gateway</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will send the information that we have a default gateway.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>ospf.originatealways</id>
|
||||
<label>Always Advertise Default Gateway</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will send the information that we have a default gateway, regardless of if it is available.</help>
|
||||
</field>
|
||||
|
||||
</form>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>ospf6.enabled</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will activate the OSPFv3 service if routing protocols are enabled in "General".</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>ospf6.redistribute</id>
|
||||
<label>Route Redistribution</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<help><![CDATA[Select other routing sources, which should be redistributed to the other nodes.]]></help>
|
||||
<hint>Type or select a route source.</hint>
|
||||
</field>
|
||||
<field>
|
||||
<id>ospf6.routerid</id>
|
||||
<label>Router ID</label>
|
||||
<type>text</type>
|
||||
<help>Router ID as IPv4 Address</help>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>rip.enabled</id>
|
||||
<label>enable</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will activate the RIP service if the support of routing protocols is enabled in "General".</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rip.version</id>
|
||||
<label>Version</label>
|
||||
<type>text</type>
|
||||
<help>Choose your RIP version (1 or 2). 1 is classful, 2 supports CIDR.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rip.passiveinterfaces</id>
|
||||
<label>Passive Interfaces</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<help><![CDATA[Select the interfaces, where no RIP packets should be sent to.]]></help>
|
||||
<hint>Type or select interface.</hint>
|
||||
</field>
|
||||
<field>
|
||||
<id>rip.redistribute</id>
|
||||
<label>Route Redistribution</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<help><![CDATA[Select other routing sources, which should be redistributed to the other nodes.]]></help>
|
||||
<hint>Type or select a route source.</hint>
|
||||
</field>
|
||||
<field>
|
||||
<id>rip.networks</id>
|
||||
<label>Networks</label>
|
||||
<style>tokenize</style>
|
||||
<type>select_multiple</type>
|
||||
<allownew>true</allownew>
|
||||
<help>Enter your networks in CIDR notation like 127.0.0.0/8.</help>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<acl>
|
||||
<page-routing>
|
||||
<name>Routing</name>
|
||||
<patterns>
|
||||
<pattern>ui/quagga/*</pattern>
|
||||
<pattern>api/quagga/*</pattern>
|
||||
</patterns>
|
||||
</page-routing>
|
||||
</acl>
|
||||
30
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.php
Normal file
30
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.php
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
namespace OPNsense\Quagga;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
/*
|
||||
Copyright (C) 2017 Fabian Franz
|
||||
Copyright (C) 2017 Michael Muenz
|
||||
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.
|
||||
*/
|
||||
class BGP extends BaseModel
|
||||
{
|
||||
}
|
||||
220
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.xml
Normal file
220
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.xml
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
<model>
|
||||
<mount>//OPNsense/quagga/bgp</mount>
|
||||
<description>BGP Routing configuration</description>
|
||||
<items>
|
||||
<enabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<asnumber type="IntegerField">
|
||||
<default></default>
|
||||
<Required>Y</Required>
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
</asnumber>
|
||||
<networks type="CSVListField">
|
||||
<default></default>
|
||||
<Required>N</Required>
|
||||
<mask>/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2},)*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2})$/</mask>
|
||||
</networks>
|
||||
<redistribute type="OptionField">
|
||||
<Required>N</Required>
|
||||
<multiple>Y</multiple>
|
||||
<default></default>
|
||||
<OptionValues>
|
||||
<babel>Babel routing protocol (Babel)</babel>
|
||||
<ospf>Open Shortest Path First (OSPF)</ospf>
|
||||
<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>
|
||||
<rip>Routing Information Protocol (RIP)</rip>
|
||||
<static>Statically configured routes</static>
|
||||
</OptionValues>
|
||||
</redistribute>
|
||||
<neighbors>
|
||||
<neighbor type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<address type="TextField">
|
||||
<default></default>
|
||||
<Required>Y</Required>
|
||||
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
|
||||
</address>
|
||||
<remoteas type="IntegerField">
|
||||
<default></default>
|
||||
<Required>Y</Required>
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
</remoteas>
|
||||
<updatesource type="InterfaceField">
|
||||
<default></default>
|
||||
<Required>N</Required>
|
||||
<multiple>N</multiple>
|
||||
<filters>
|
||||
<enable>/^(?!0).*$/</enable>
|
||||
</filters>
|
||||
</updatesource>
|
||||
<nexthopself type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</nexthopself>
|
||||
<defaultoriginate type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</defaultoriginate>
|
||||
<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>
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
namespace OPNsense\Quagga;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
class General extends BaseModel
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<model>
|
||||
<mount>//OPNsense/quagga/general</mount>
|
||||
<description>Quagga Routing configuration</description>
|
||||
<items>
|
||||
<enabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<enablelogfile type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</enablelogfile>
|
||||
<logfilelevel type="OptionField">
|
||||
<Required>Y</Required>
|
||||
<multiple>N</multiple>
|
||||
<default>notifications</default>
|
||||
<OptionValues>
|
||||
<critical>Critical</critical>
|
||||
<emergencies>Emergencies</emergencies>
|
||||
<errors>Errors</errors>
|
||||
<alerts>Alerts</alerts>
|
||||
<warnings>Warnings</warnings>
|
||||
<notifications>Notifications</notifications>
|
||||
<informational>Informational</informational>
|
||||
<debugging>Debugging</debugging>
|
||||
</OptionValues>
|
||||
</logfilelevel>
|
||||
<enablesyslog type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</enablesyslog>
|
||||
<sysloglevel type="OptionField">
|
||||
<Required>Y</Required>
|
||||
<multiple>N</multiple>
|
||||
<default>notifications</default>
|
||||
<OptionValues>
|
||||
<critical>Critical</critical>
|
||||
<emergencies>Emergencies</emergencies>
|
||||
<errors>Errors</errors>
|
||||
<alerts>Alerts</alerts>
|
||||
<warnings>Warnings</warnings>
|
||||
<notifications>Notifications</notifications>
|
||||
<informational>Informational</informational>
|
||||
<debugging>Debugging</debugging>
|
||||
</OptionValues>
|
||||
</sysloglevel>
|
||||
</items>
|
||||
</model>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<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" />
|
||||
<!--<ISIS VisibleName="IS-IS" cssClass="fa fa-bolt fa-fw" url="/ui/quagga/isis/index" order="30" />-->
|
||||
<BGP VisibleName="BGPv4" cssClass="fa fa-globe fa-fw" url="/ui/quagga/bgp/index" order="40" />
|
||||
<Diagnostics VisibleName="Diagnostics" cssClass="fa fa-medkit fa-fw" order="50">
|
||||
<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" />
|
||||
<BGP VisibleName="BGPv4" url="/ui/quagga/diagnostics/bgp" order="40" />
|
||||
<LOG VisibleName="Log" url="/ui/quagga/diagnostics/log" order="100" />
|
||||
</Diagnostics>
|
||||
</Routing>
|
||||
</menu>
|
||||
34
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/OSPF.php
Normal file
34
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/OSPF.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
namespace OPNsense\Quagga;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
class OSPF extends BaseModel
|
||||
{
|
||||
}
|
||||
206
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/OSPF.xml
Normal file
206
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/OSPF.xml
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
<model>
|
||||
<mount>//OPNsense/quagga/ospf</mount>
|
||||
<description>OSPF Routing configuration</description>
|
||||
<items>
|
||||
<enabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<routerid type="TextField">
|
||||
<default></default>
|
||||
<Required>N</Required>
|
||||
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
|
||||
</routerid>
|
||||
<originate type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</originate>
|
||||
<originatealways type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</originatealways>
|
||||
<passiveinterfaces type="InterfaceField">
|
||||
<Required>N</Required>
|
||||
<multiple>Y</multiple>
|
||||
<default></default>
|
||||
<filters>
|
||||
<enable>/^(?!0).*$/</enable>
|
||||
</filters>
|
||||
</passiveinterfaces>
|
||||
<redistribute type="OptionField">
|
||||
<Required>N</Required>
|
||||
<multiple>Y</multiple>
|
||||
<default></default>
|
||||
<OptionValues>
|
||||
<bgp>Border Gateway Protocol (BGP)</bgp>
|
||||
<connected>Connected routes (directly attached subnet or host)</connected>
|
||||
<kernel>Kernel routes (not installed via the zebra RIB)</kernel>
|
||||
<rip>Routing Information Protocol (RIP)</rip>
|
||||
<static>Statically configured routes</static>
|
||||
</OptionValues>
|
||||
</redistribute>
|
||||
<networks>
|
||||
<network type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<ipaddr type="TextField">
|
||||
<default></default>
|
||||
<Required>Y</Required>
|
||||
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
|
||||
</ipaddr>
|
||||
<area type="TextField">
|
||||
<default></default>
|
||||
<Required>Y</Required>
|
||||
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
|
||||
</area>
|
||||
<netmask type="IntegerField">
|
||||
<default>24</default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>Y</Required>
|
||||
<MaximumValue>32</MaximumValue>
|
||||
<ValidationMessage>Network mask must be between 0 and 32.</ValidationMessage>
|
||||
</netmask>
|
||||
<linkedPrefixlistIn type="ModelRelationField">
|
||||
<Model>
|
||||
<template>
|
||||
<source>OPNsense.quagga.ospf</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.ospf</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>
|
||||
</network>
|
||||
</networks>
|
||||
<interfaces>
|
||||
<interface type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<interfacename type="InterfaceField">
|
||||
<Required>N</Required>
|
||||
<multiple>N</multiple>
|
||||
<default></default>
|
||||
<filters>
|
||||
<enable>/^(?!0).*$/</enable>
|
||||
</filters>
|
||||
</interfacename>
|
||||
<authtype type="OptionField">
|
||||
<Required>N</Required>
|
||||
<multiple>N</multiple>
|
||||
<default></default>
|
||||
<OptionValues>
|
||||
<message-digest>MD5</message-digest>
|
||||
</OptionValues>
|
||||
</authtype>
|
||||
<authkey type="TextField">
|
||||
<default></default>
|
||||
<Required>N</Required>
|
||||
<mask>/^\S+$/</mask>
|
||||
</authkey>
|
||||
<cost type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Cost must be between 0 and 4294967295.</ValidationMessage>
|
||||
</cost>
|
||||
<hellointerval type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Hello interval must be between 0 and 4294967295.</ValidationMessage>
|
||||
</hellointerval>
|
||||
<deadinterval type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Dead interval must be between 0 and 4294967295.</ValidationMessage>
|
||||
</deadinterval>
|
||||
<retransmitinterval type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Retransmit interval must be between 0 and 4294967295.</ValidationMessage>
|
||||
</retransmitinterval>
|
||||
<transmitdelay type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Transmit delay must be between 0 and 4294967295.</ValidationMessage>
|
||||
</transmitdelay>
|
||||
<priority type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Priority must be between 0 and 4294967295.</ValidationMessage>
|
||||
</priority>
|
||||
<networktype type="OptionField">
|
||||
<Required>N</Required>
|
||||
<multiple>N</multiple>
|
||||
<default></default>
|
||||
<OptionValues>
|
||||
<broadcast>Broadcast multi-access network</broadcast>
|
||||
<non-broadcast>NBMA network</non-broadcast>
|
||||
<point-to-multipoint>Point-to-multipoint network</point-to-multipoint>
|
||||
<point-to-point>Point-to-point network</point-to-point>
|
||||
</OptionValues>
|
||||
</networktype>
|
||||
</interface>
|
||||
</interfaces>
|
||||
<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>
|
||||
</items>
|
||||
</model>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/*
|
||||
Copyright (C) 2017 Fabian Franz
|
||||
Copyright (C) 2017 Michael Muenz
|
||||
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\BaseModel;
|
||||
|
||||
class OSPF6 extends BaseModel
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
<model>
|
||||
<mount>//OPNsense/quagga/ospf6</mount>
|
||||
<description>OSPFv3 Routing configuration</description>
|
||||
<items>
|
||||
<enabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<redistribute type="OptionField">
|
||||
<Required>N</Required>
|
||||
<multiple>Y</multiple>
|
||||
<default></default>
|
||||
<OptionValues>
|
||||
<connected>Connected routes (directly attached subnet or host)</connected>
|
||||
<static>Statically configured routes</static>
|
||||
</OptionValues>
|
||||
</redistribute>
|
||||
<routerid type="TextField">
|
||||
<default></default>
|
||||
<Required>Y</Required>
|
||||
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
|
||||
</routerid>
|
||||
<interfaces>
|
||||
<interface type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<interfacename type="InterfaceField">
|
||||
<Required>N</Required>
|
||||
<multiple>N</multiple>
|
||||
<default></default>
|
||||
<filters>
|
||||
<enable>/^(?!0).*$/</enable>
|
||||
</filters>
|
||||
</interfacename>
|
||||
<area type="TextField">
|
||||
<default></default>
|
||||
<Required>Y</Required>
|
||||
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
|
||||
</area>
|
||||
<cost type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Cost must be between 0 and 4294967295.</ValidationMessage>
|
||||
</cost>
|
||||
<hellointerval type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Hello interval must be between 0 and 4294967295.</ValidationMessage>
|
||||
</hellointerval>
|
||||
<deadinterval type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Dead interval must be between 0 and 4294967295.</ValidationMessage>
|
||||
</deadinterval>
|
||||
<retransmitinterval type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Retransmit interval must be between 0 and 4294967295.</ValidationMessage>
|
||||
</retransmitinterval>
|
||||
<transmitdelay type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Transmit delay must be between 0 and 4294967295.</ValidationMessage>
|
||||
</transmitdelay>
|
||||
<priority type="IntegerField">
|
||||
<default></default>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<Required>N</Required>
|
||||
<MaximumValue>4294967295</MaximumValue>
|
||||
<ValidationMessage>Priority must be between 0 and 4294967295.</ValidationMessage>
|
||||
</priority>
|
||||
<networktype type="OptionField">
|
||||
<Required>N</Required>
|
||||
<multiple>N</multiple>
|
||||
<default></default>
|
||||
<OptionValues>
|
||||
<broadcast>Broadcast multi-access network</broadcast>
|
||||
<non-broadcast>NBMA network</non-broadcast>
|
||||
<point-to-multipoint>Point-to-multipoint network</point-to-multipoint>
|
||||
<point-to-point>Point-to-point network</point-to-point>
|
||||
</OptionValues>
|
||||
</networktype>
|
||||
</interface>
|
||||
</interfaces>
|
||||
</items>
|
||||
</model>
|
||||
34
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/RIP.php
Normal file
34
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/RIP.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
namespace OPNsense\Quagga;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
class RIP extends BaseModel
|
||||
{
|
||||
}
|
||||
45
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/RIP.xml
Normal file
45
net/frr/src/opnsense/mvc/app/models/OPNsense/Quagga/RIP.xml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<model>
|
||||
<mount>//OPNsense/quagga/rip</mount>
|
||||
<description>RIP Routing configuration</description>
|
||||
<items>
|
||||
<enabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<version type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>2</MaximumValue>
|
||||
<default>2</default>
|
||||
<Required>Y</Required>
|
||||
</version>
|
||||
<networks type="CSVListField">
|
||||
<default></default>
|
||||
<Required>Y</Required>
|
||||
<mask>/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2},)*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2})$/</mask>
|
||||
</networks>
|
||||
|
||||
<passiveinterfaces type="InterfaceField">
|
||||
<Required>N</Required>
|
||||
<multiple>Y</multiple>
|
||||
<default></default>
|
||||
<filters>
|
||||
<enable>/^(?!0).*$/</enable>
|
||||
</filters>
|
||||
</passiveinterfaces>
|
||||
<redistribute type="OptionField">
|
||||
<Required>N</Required>
|
||||
<multiple>Y</multiple>
|
||||
<default></default>
|
||||
<OptionValues>
|
||||
<babel>Babel routing protocol (Babel)</babel>
|
||||
<bgp>Border Gateway Protocol (BGP)</bgp>
|
||||
<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>
|
||||
<ospf>Open Shortest Path First (OSPF)</ospf>
|
||||
<static>Statically configured routes</static>
|
||||
</OptionValues>
|
||||
</redistribute>
|
||||
</items>
|
||||
</model>
|
||||
226
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/bgp.volt
Normal file
226
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/bgp.volt
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
{#
|
||||
|
||||
OPNsense® is Copyright © 2014 – 2017 by Deciso B.V.
|
||||
Copyright (C) 2017 Fabian Franz
|
||||
Copyright (C) 2017 Michael Muenz
|
||||
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.
|
||||
|
||||
#}
|
||||
<!-- 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="#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">
|
||||
<div class="content-box" style="padding-bottom: 1.5em;">
|
||||
{{ partial("layout_partials/base_form",['fields':bgpForm,'id':'frm_bgp_settings'])}}
|
||||
|
||||
<hr />
|
||||
<div class="col-md-12">
|
||||
<button class="btn btn-primary" id="saveAct" type="button"><b>{{ lang._('Save') }}</b></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="neighbors" class="tab-pane fade in">
|
||||
<table id="grid-neighbors" class="table table-responsive" data-editDialog="DialogEditBGPNeighbor">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
|
||||
<th data-column-id="address" data-type="string" data-visible="true">{{ lang._('Neighbor Address') }}</th>
|
||||
<th data-column-id="remoteas" data-type="string" data-visible="true">{{ lang._('Remote AS') }}</th>
|
||||
<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>
|
||||
</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="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">
|
||||
$(document).ready(function() {
|
||||
var data_get_map = {'frm_bgp_settings':"/api/quagga/bgp/get"};
|
||||
mapDataToFormUI(data_get_map).done(function(data){
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
|
||||
// link save button to API set action
|
||||
$("#saveAct").click(function(){
|
||||
saveFormToEndpoint(url="/api/quagga/bgp/set",formid='frm_bgp_settings',callback_ok=function(){
|
||||
ajaxCall(url="/api/quagga/service/reconfigure", sendData={}, callback=function(data,status) {
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
$("#grid-neighbors").UIBootgrid(
|
||||
{ 'search':'/api/quagga/bgp/searchNeighbor',
|
||||
'get':'/api/quagga/bgp/getNeighbor/',
|
||||
'set':'/api/quagga/bgp/setNeighbor/',
|
||||
'add':'/api/quagga/bgp/addNeighbor/',
|
||||
'del':'/api/quagga/bgp/delNeighbor/',
|
||||
'toggle':'/api/quagga/bgp/toggleNeighbor/',
|
||||
'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')])}}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
{#
|
||||
|
||||
OPNsense® is Copyright © 2014 – 2017 by Deciso B.V.
|
||||
Copyright (C) 2017 Fabian Franz
|
||||
Copyright (C) 2017 Michael Muenz
|
||||
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.
|
||||
|
||||
#}
|
||||
|
||||
{#
|
||||
{{ partial("layout_partials/base_form",['fields':diagnosticsForm,'id':'frm_diagnostics_settings'])}}
|
||||
#}
|
||||
|
||||
<script type="text/x-template" id="overviewtpl">
|
||||
<table>
|
||||
<tr>
|
||||
<td>{{ lang._('Table Version') }}</td>
|
||||
<td><%= bgp_overview['table_version'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Local Router ID') }}</td>
|
||||
<td><%= bgp_overview['local_router_id'] %></td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ lang._('Status') }}</th>
|
||||
<th>{{ lang._('Network') }}</th>
|
||||
<th>{{ lang._('Next Hop') }}</th>
|
||||
<th>{{ lang._('Metric') }}</th>
|
||||
<th>{{ lang._('LocPrf') }}</th>
|
||||
<th>{{ lang._('Weight') }}</th>
|
||||
<th>{{ lang._('Path') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(bgp_overview['output'], function (row) { %>
|
||||
<tr>
|
||||
<td>
|
||||
<% _.each(row['status'], function(element) { %>
|
||||
<abbr title="<%= translate(element['dn']) %>"><%= element['abb'] %></abbr>
|
||||
<% }) %>
|
||||
</td>
|
||||
<td><%= row['Network'] %></td>
|
||||
<td><%= row['Next Hop'] %></td>
|
||||
<td><%= row['Metric'] %></td>
|
||||
<td><%= row['LocPrf'] %></td>
|
||||
<td><%= row['Weight'] %></td>
|
||||
<td>
|
||||
<% _.each(row['Path'], function(element) { %>
|
||||
<abbr title="<%= translate(element['dn']) %>"><%= element['abb'] %></abbr>
|
||||
<% }) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
</script>
|
||||
<script type="text/javascript" src="/ui/js/quagga/lodash.js"></script>
|
||||
<script type="text/javascript">
|
||||
function translate(x) {
|
||||
return x;
|
||||
}
|
||||
$(document).ready(function() {
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
|
||||
ajaxCall(url="/api/quagga/diagnostics/showipbgp", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#overviewtpl').html())(data['response'])
|
||||
$('#overview').html(content)
|
||||
});
|
||||
|
||||
ajaxCall(url="/api/quagga/diagnostics/showipbgpsummary", sendData={}, callback=function(data,status) {
|
||||
$("#summarycontent").text(data['response']);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Navigation bar -->
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" href="#overview">{{ lang._('Overview') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#summary">{{ lang._('Summary') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content content-box tab-content">
|
||||
<div id="overview" class="tab-pane fade in active">
|
||||
{{ lang._('loading...') }}
|
||||
</div>
|
||||
<div id="summary" class="tab-pane fade in">
|
||||
<pre id="summarycontent"></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
{#
|
||||
|
||||
OPNsense® is Copyright © 2014 – 2017 by 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 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 type="text/javascript" src="/ui/js/quagga/lodash.js"></script>
|
||||
<script type="text/x-template" id="routestpl">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="code" data-type="raw">{{ lang._('Code') }}</th>
|
||||
<th data-column-id="network" data-type="string">{{ lang._('Network') }}</th>
|
||||
<th data-column-id="ad" data-type="numeric">{{ lang._('Administrative Distance') }}</th>
|
||||
<th data-column-id="metric" data-type="numeric">{{ lang._('Metric') }}</th>
|
||||
<th data-column-id="interface" data-type="string">{{ lang._('Interface') }}</th>
|
||||
<th data-column-id="time" data-type="string">{{ lang._('Time') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(general_routes, function(entry) { %>
|
||||
<tr>
|
||||
<td>
|
||||
<% _.each(entry['code'], function(code) { %>
|
||||
<abbr title="<%= translate(code['long']) %>"><%= (code['short']) %></abbr>
|
||||
<% }); %>
|
||||
</td>
|
||||
<td><%= entry['network'] %></td>
|
||||
<td><%= entry['ad'] %></td>
|
||||
<td><%= entry['metric'] %></td>
|
||||
<td><%= entry['interface'] %></td>
|
||||
<td><%= entry['time'] %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
function translate(content) {
|
||||
tr = {};
|
||||
tr['kernel route'] = '{{ lang._('Kernel Route') }}';
|
||||
tr['FIB route'] = '{{ lang._('FIB Route') }}';
|
||||
tr['connected'] = '{{ lang._('Connected') }}';
|
||||
tr['selected route'] = '{{ lang._('Selected Route') }}';
|
||||
tr['OSPF'] = '{{ lang._('OSPF') }}';
|
||||
tr['RIP'] = '{{ lang._('RIP') }}';
|
||||
tr['BGP'] = '{{ lang._('BGP') }}';
|
||||
if (_.has(tr,content))
|
||||
{
|
||||
return tr[content];
|
||||
}
|
||||
else
|
||||
{
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
dataconverters = {
|
||||
boolean: {
|
||||
from: function (value) { return (value == 'true') || (value == true); },
|
||||
to: function (value) { return checkmark(value) }
|
||||
},
|
||||
raw: {
|
||||
from: function (value) {
|
||||
console.log(value)
|
||||
return value
|
||||
},
|
||||
to: function (value) {
|
||||
console.log(value);
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status'])
|
||||
});
|
||||
ajaxCall(url="/api/quagga/diagnostics/generalroutes", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#routestpl').html())(data['response'])
|
||||
$('#routing').html(content)
|
||||
//$('#routing table').bootgrid({converters: dataconverters})
|
||||
});
|
||||
ajaxCall(url="/api/quagga/diagnostics/generalroutes6", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#routestpl').html())({general_routes: data['response']['general_routes6']})
|
||||
$('#routing6').html(content)
|
||||
//$('#routing6 table').bootgrid({converters: dataconverters})
|
||||
});
|
||||
ajaxCall(url="/api/quagga/diagnostics/showrunningconfig", sendData={}, callback=function(data,status) {
|
||||
$("#runningconfig").text(data['response']);
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Navigation bar -->
|
||||
<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>
|
||||
|
|
@ -0,0 +1,484 @@
|
|||
{#
|
||||
|
||||
OPNsense® is Copyright © 2014 – 2017 by 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 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 type="text/x-template" id="overviewtpl">
|
||||
<h2>{{ lang._('General') }}</h2>
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ lang._('RFC2328 Conform') }}</td>
|
||||
<td><%= checkmark(ospf_overview['rfc2328_conform']) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('ASBR') }}</td>
|
||||
<td><%= checkmark(ospf_overview['asbr']) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Router ID') }}</td>
|
||||
<td><%= ospf_overview['router_id'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('RFC1583 Compatibility') }}</td>
|
||||
<td><%= checkmark(ospf_overview['rfc1583_compatibility']) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Opaque Capability') }}</td>
|
||||
<td><%= checkmark(ospf_overview['opaque_capability']) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Initial SPF Scheduling Delay') }}</td>
|
||||
<td><%= ospf_overview['initial_spf_scheduling_delay'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Minimum Hold Time') }}</td>
|
||||
<td><%= ospf_overview['hold_time']['min'] %> {{ lang._('Milliseconds') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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><%= ospf_overview['current_hold_time_multipier'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('SPF Timer') }}</td>
|
||||
<td><%= ospf_overview['spf_timer'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Refresh Timer') }}</td>
|
||||
<td><%= ospf_overview['refresh_timer'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Areas Attached Count') }}</td>
|
||||
<td><%= ospf_overview['areas_attached_count'] %></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>{{ lang._('Link State Area') }}</h2>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{{ lang._('Count') }}</th>
|
||||
<th>{{ lang._('Checksum') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ lang._('External LSA') }}</td>
|
||||
<td><%= ospf_overview['external_lsa']['count'] %></td>
|
||||
<td><%= ospf_overview['external_lsa']['checksum'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Opaque AS LSA') }}</td>
|
||||
<td><%= ospf_overview['opaque_as_lsa']['count'] %></td>
|
||||
<td><%= ospf_overview['opaque_as_lsa']['checksum'] %></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>{{ lang._('Areas') }}</h2>
|
||||
|
||||
<% if (ospf_overview['areas']) { %>
|
||||
<% areas = ospf_overview['areas'] %>
|
||||
<% _.each(_.keys(areas), function(areaname) { %>
|
||||
<% area = areas[areaname] %>
|
||||
<h3><%= areaname %></h3>
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ lang._('Interfaces: Total') }}</td>
|
||||
<td><%= area['interfaces']['total'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Interfaces: Active') }}</td>
|
||||
<td><%= area['interfaces']['active'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Fully Adjacent Neighbor Count') }}</td>
|
||||
<td><%= area['fully_adjacent_neighbor_count'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('SPF Execution Count') }}</td>
|
||||
<td><%= area['spf_exec_count'] %></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{{ lang._('Count') }}</th>
|
||||
<th>{{ lang._('Checksum') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(_.keys(area['lsa']), function(lsaname) { %>
|
||||
<% lsa = area['lsa'][lsaname] %>
|
||||
<tr>
|
||||
<td><%= translate(lsaname) %></td>
|
||||
<td><%= lsa['count'] %></td>
|
||||
<td><%= lsa['checksum'] %></td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</script>
|
||||
<script type="text/x-template" id="databasetpl">
|
||||
<% _.each(_.keys(ospf_database), function(router_id) { %>
|
||||
<h1>{{ lang._('Router ID:')}} <%= router_id %></h1>
|
||||
<hr />
|
||||
<h2>{{ lang._('Router Link State Area') }}</h2>
|
||||
<% _.each(_.keys(ospf_database[router_id]['router_link_state_area']), function(area) { %>
|
||||
<h3>Area <%= area %></h3>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="linkid" data-type="string">{{ lang._('Link ID') }}</th>
|
||||
<th data-column-id="advrouter" data-type="string">{{ lang._('ADV Router') }}</th>
|
||||
<th data-column-id="age" data-type="numeric">{{ lang._('Age') }}</th>
|
||||
<th data-column-id="seqnr" data-type="string">{{ lang._('Sequence Number') }}</th>
|
||||
<th data-column-id="cksum" data-type="string">{{ lang._('Checksum') }}</th>
|
||||
<th data-column-id="linkcnt" data-type="numeric">{{ lang._('Link Count') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(ospf_database[router_id]['router_link_state_area'][area], function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry["Link ID"] %></td>
|
||||
<td><%= entry["ADV Router"] %></td>
|
||||
<td><%= entry["Age"] %></td>
|
||||
<td><%= entry["Seq#"] %></td>
|
||||
<td><%= entry["CkSum"] %></td>
|
||||
<td><%= entry["Link count"] %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }); %>
|
||||
<h2>{{ lang._('Net Link State Area') }}</h2>
|
||||
<% _.each(_.keys(ospf_database[router_id]['net_link_state_area']), function(area) { %>
|
||||
<h3>{{ lang._('Area:') }} <%= area %></h3>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="linkid" data-type="string">{{ lang._('Link ID') }}</th>
|
||||
<th data-column-id="advrouter" data-type="string">{{ lang._('ADV Router') }}</th>
|
||||
<th data-column-id="age" data-type="numeric">{{ lang._('Age') }}</th>
|
||||
<th data-column-id="seqnr" data-type="string">{{ lang._('Sequence Number') }}</th>
|
||||
<th data-column-id="cksum" data-type="string">{{ lang._('Checksum') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(ospf_database[router_id]['net_link_state_area'][area], function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry["Link ID"] %></td>
|
||||
<td><%= entry["ADV Router"] %></td>
|
||||
<td><%= entry["Age"] %></td>
|
||||
<td><%= entry["Seq#"] %></td>
|
||||
<td><%= entry["CkSum"] %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }); %>
|
||||
<h2>{{ lang._('External States') }}</h2>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="linkid" data-type="string">{{ lang._('Link ID') }}</th>
|
||||
<th data-column-id="advrouter" data-type="string">{{ lang._('ADV Router') }}</th>
|
||||
<th data-column-id="age" data-type="numeric">{{ lang._('Age') }}</th>
|
||||
<th data-column-id="seqnr" data-type="string">{{ lang._('Sequence Number') }}</th>
|
||||
<th data-column-id="chsum" data-type="string">{{ lang._('Checksum') }}</th>
|
||||
<th data-column-id="route" data-type="string">{{ lang._('Route') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(ospf_database[router_id]['external_states'], function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry["Link ID"] %></td>
|
||||
<td><%= entry["ADV Router"] %></td>
|
||||
<td><%= entry["Age"] %></td>
|
||||
<td><%= entry["Seq#"] %></td>
|
||||
<td><%= entry["CkSum"] %></td>
|
||||
<td><%= entry["Route"] %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }); %>
|
||||
</script>
|
||||
<script type="text/x-template" id="routestpl">
|
||||
<h2>{{ lang._('Network Routing Table') }}</h2>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="type" data-type="string">{{ lang._('Type') }}</th>
|
||||
<th data-column-id="network" data-type="string">{{ lang._('Network') }}</th>
|
||||
<th data-column-id="cost" data-type="numeric">{{ lang._('Cost') }}</th>
|
||||
<th data-column-id="area" data-type="numeric">{{ lang._('Area') }}</th>
|
||||
<th data-column-id="via" data-type="string">{{ lang._('Via') }}</th>
|
||||
<th data-column-id="viainterface" data-type="string">{{ lang._('Via interface') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(ospf_route['OSPF network routing table'], function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry["type"] %></td>
|
||||
<td><%= entry["network"] %></td>
|
||||
<td><%= entry["cost"] %></td>
|
||||
<td><%= entry["area"] %></td>
|
||||
<td><%= translate(entry["via"]) %></td>
|
||||
<td><%= entry["via_interface"] %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>{{ lang._('Router Routing Table') }}</h2>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="type" data-type="string">{{ lang._('Type') }}</th>
|
||||
<th data-column-id="cost" data-type="numeric">{{ lang._('Cost') }}</th>
|
||||
<th data-column-id="area" data-type="string">{{ lang._('Area') }}</th>
|
||||
<th data-column-id="asbr" data-type="boolean">{{ lang._('ASBR') }}</th>
|
||||
<th data-column-id="via" data-type="string">{{ lang._('Via') }}</th>
|
||||
<th data-column-id="viainterface" data-type="string">{{ lang._('Via interface') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(ospf_route['OSPF router routing table'], function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry["type"] %></td>
|
||||
<td><%= entry["cost"] %></td>
|
||||
<td><%= entry["area"] %></td>
|
||||
<td><%= entry["asbr"] %></td>
|
||||
<td><%= translate(entry["via"]) %></td>
|
||||
<td><%= entry["via_interface"] %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>{{ lang._('External Routing Table') }}</h2>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="type" data-type="string">{{ lang._('Type') }}</th>
|
||||
<th data-column-id="network" data-type="string">{{ lang._('Network') }}</th>
|
||||
<th data-column-id="cost" data-type="string">{{ lang._('Cost') }}</th>
|
||||
<th data-column-id="tag" data-type="string">{{ lang._('Tag') }}</th>
|
||||
<th data-column-id="via" data-type="string">{{ lang._('Via') }}</th>
|
||||
<th data-column-id="viainterface" data-type="string">{{ lang._('Via interface') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(ospf_route['OSPF external routing table'], function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry["type"] %></td>
|
||||
<td><%= entry["network"] %></td>
|
||||
<td><%= entry["cost"] %></td>
|
||||
<td><%= entry["tag"] %></td>
|
||||
<td><%= translate(entry["via"]) %></td>
|
||||
<td><%= entry["via_interface"] %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
</script>
|
||||
<script type="text/x-template" id="neighbortpl">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="neighborid" data-type="string">{{ lang._('Neighbor ID') }}</th>
|
||||
<th data-column-id="priority" data-type="numeric">{{ lang._('Priority') }}</th>
|
||||
<th data-column-id="state" data-type="string">{{ lang._('State') }}</th>
|
||||
<th data-column-id="deadtime" data-type="string">{{ lang._('Dead Time') }}</th>
|
||||
<th data-column-id="address" data-type="string">{{ lang._('Address') }}</th>
|
||||
<th data-column-id="interface" data-type="string">{{ lang._('Interface') }}</th>
|
||||
<th data-column-id="rxmtl" data-type="numeric">RXmtL</th>
|
||||
<th data-column-id="rqstl" data-type="numeric">RqstL</th>
|
||||
<th data-column-id="dbsml" data-type="numeric">DBsmL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(ospf_neighbors, function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry["Neighbor ID"] %></td>
|
||||
<td><%= entry["Pri"] %></td>
|
||||
<td><%= translate(entry["State"]) %></td>
|
||||
<td><%= entry["Dead Time"] %></td>
|
||||
<td><%= entry["Address"] %></td>
|
||||
<td><%= entry["Interface"] %></td>
|
||||
<td><%= entry["RXmtL"] %></td>
|
||||
<td><%= entry["RqstL"] %></td>
|
||||
<td><%= entry["DBsmL"] %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
</script>
|
||||
<script type="text/x-template" id="interfacetpl">
|
||||
<% _.each(_.keys(ospf_interface), function(interfacename) { %>
|
||||
<% int = ospf_interface[interfacename] %>
|
||||
<h2><%= interfacename %></h2>
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<% _.each(_.keys(int), function(propertyname) { %>
|
||||
<tr>
|
||||
<td><%= translate(propertyname) %></td>
|
||||
<td>
|
||||
<% if (int[propertyname] === false || int[propertyname] === true) { %>
|
||||
<%= checkmark(int[propertyname]) %>
|
||||
<% } else if (propertyname == 'intervals') { %>
|
||||
{{ lang._('Hello Interval:') }} <%= int[propertyname]['hello'] %><br />
|
||||
{{ lang._('Dead Interval:') }} <%= int[propertyname]['dead'] %><br />
|
||||
{{ lang._('Wait Interval:') }} <%= int[propertyname]['wait'] %><br />
|
||||
{{ lang._('Retransmit Interval:') }} <%= int[propertyname]['retransmit'] %>
|
||||
<% } else { %>
|
||||
<%= int[propertyname] %>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }) %>
|
||||
</script>
|
||||
<script type="text/javascript" src="/ui/js/quagga/lodash.js"></script>
|
||||
<script>
|
||||
|
||||
function translate(data)
|
||||
{
|
||||
tr = []
|
||||
tr['count'] = '{{ lang._('Count') }}'
|
||||
tr['router'] = '{{ lang._('Router') }}'
|
||||
tr['network'] = '{{ lang._('Network') }}'
|
||||
tr['summary'] = '{{ lang._('Summary') }}'
|
||||
tr['ASBR summary'] = '{{ lang._('ASBR summary') }}'
|
||||
tr['NSSA'] = '{{ lang._('NSSA') }}'
|
||||
tr['directly attached'] = '{{ lang._('Directly Attached') }}'
|
||||
tr['Full/DR'] = '{{ lang._('Full (Designated Router)') }}'
|
||||
tr['enabled'] = '{{ lang._('Enabled') }}'
|
||||
tr['cost'] = '{{ lang._('Cost') }}'
|
||||
tr['priority'] = '{{ lang._('Priority') }}'
|
||||
tr['router_id'] = '{{ lang._('Router ID') }}'
|
||||
tr['network_type'] = '{{ lang._('Network Type') }}'
|
||||
tr['area'] = '{{ lang._('Area') }}'
|
||||
tr['transmit_delay'] = '{{ lang._('Transmit Delay') }}'
|
||||
tr['state'] = '{{ lang._('State') }}'
|
||||
tr['broadcast'] = '{{ lang._('Broadcast') }}'
|
||||
tr['mtu_mismatch_detection'] = '{{ lang._('MTU Mismatch Detection') }}'
|
||||
tr['address'] = '{{ lang._('Address') }}'
|
||||
tr['designated_router'] = '{{ lang._('Designated Router') }}'
|
||||
tr['designated_router_interface_address'] = '{{ lang._('Designated Router Interface Address') }}'
|
||||
tr['backup_designated_router'] = '{{ lang._('Backup Designated Router') }}'
|
||||
tr['multicast_group_memberships'] = '{{ lang._('Multicast Group Memberships') }}'
|
||||
tr['intervals'] = '{{ lang._('Intervals') }}'
|
||||
tr['hello_due_in'] = '{{ lang._('Hello Due In') }}'
|
||||
tr['neighbor_count'] = '{{ lang._('Neighbor Count') }}'
|
||||
tr['adjacent_neighbor_count'] = '{{ lang._('Adjacent Neighbor Count') }}'
|
||||
return _.has(tr,data) ? tr[data] : data
|
||||
}
|
||||
|
||||
function checkmark(bin)
|
||||
{
|
||||
return "<i class=\"fa " + (bin ? "fa-check-square" : "fa-square") + " text-muted\"></i>";
|
||||
}
|
||||
|
||||
dataconverters = {
|
||||
boolean: {
|
||||
from: function (value) { return (value == 'true') || (value == true); },
|
||||
to: function (value) { return checkmark(value) }
|
||||
},
|
||||
raw: {
|
||||
from: function (value) { return value },
|
||||
to: function (value) { return value }
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status'])
|
||||
});
|
||||
|
||||
ajaxCall(url="/api/quagga/diagnostics/ospfoverview", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#overviewtpl').html())(data['response'])
|
||||
$('#overview').html(content)
|
||||
});
|
||||
ajaxCall(url="/api/quagga/diagnostics/ospfdatabase", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#databasetpl').html())(data['response'])
|
||||
$('#database').html(content)
|
||||
$('#database table').bootgrid()
|
||||
});
|
||||
ajaxCall(url="/api/quagga/diagnostics/ospfroute", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#routestpl').html())(data['response'])
|
||||
$('#routing').html(content)
|
||||
$('#routing table').bootgrid({converters: dataconverters})
|
||||
});
|
||||
ajaxCall(url="/api/quagga/diagnostics/ospfneighbor", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#neighbortpl').html())(data['response'])
|
||||
$('#neighbor').html(content)
|
||||
$('#neighbor table').bootgrid()
|
||||
});
|
||||
ajaxCall(url="/api/quagga/diagnostics/ospfinterface", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#interfacetpl').html())(data['response'])
|
||||
$('#interface').html(content)
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Navigation bar -->
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" href="#overview">{{ lang._('Overview') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#routing">{{ lang._('Routing Table') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#database">{{ lang._('Database') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#neighbor">{{ lang._('Neighbor') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#interface">{{ lang._('Interface') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content content-box tab-content">
|
||||
<div id="overview" class="tab-pane fade in active">
|
||||
</div>
|
||||
<div id="routing" class="tab-pane fade in">
|
||||
</div>
|
||||
<div id="database" class="tab-pane fade in">
|
||||
</div>
|
||||
<div id="neighbor" class="tab-pane fade in">
|
||||
</div>
|
||||
<div id="interface" class="tab-pane fade in">
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,384 @@
|
|||
{#
|
||||
|
||||
OPNsense® is Copyright © 2014 – 2017 by 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 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 type="text/x-template" id="overviewtpl">
|
||||
<h2>{{ lang._('General') }}</h2>
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ lang._('Router ID') }}</td>
|
||||
<td><%= ospfv3_overview['router_id'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Routing Process') }}</td>
|
||||
<td><%= ospfv3_overview['routing_process'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Running Time') }}</td>
|
||||
<td><%= ospfv3_overview['running_time'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Initial SPF scheduling delay') }}</td>
|
||||
<td><%= ospfv3_overview['intital_spf_scheduling_delay'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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'] %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('SPF timer') }}</td>
|
||||
<td><%= ospfv3_overview['spf_timer'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Number Of Scoped AS') }}</td>
|
||||
<td><%= ospfv3_overview['number_as_scoped'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Number Of Areas') }}</td>
|
||||
<td><%= ospfv3_overview['number_of_areas'] %></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>{{ lang._('Areas') }}</h2>
|
||||
<% if (ospfv3_overview['areas']) { %>
|
||||
<% areas = ospfv3_overview['areas'] %>
|
||||
<% _.each(_.keys(areas), function(areaname) { %>
|
||||
<% area = areas[areaname] %>
|
||||
<h3><%= areaname %></h3>
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ lang._('Number Of LSAs') }}</td>
|
||||
<td><%= area['number_lsas'] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ lang._('Interfaces') }}</td>
|
||||
<td><%= _.join(area['interfaces'], ", ") %></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="routestpl">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="flags1" data-type="string">{{ lang._('Flags 1') }}</th>
|
||||
<th data-column-id="flags2" data-type="string">{{ lang._('Flags 2') }}</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="interface" data-type="string">{{ lang._('Interface') }}</th>
|
||||
<th data-column-id="time" data-type="string">{{ lang._('Time') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(ospfv3_route, function (route) { %>
|
||||
<tr>
|
||||
<td><%= route['f1'] %></td>
|
||||
<td><%= route['f2'] %></td>
|
||||
<td><%= route['network'] %></td>
|
||||
<td><%= route['gateway'] %></td>
|
||||
<td><%= route['interface'] %></td>
|
||||
<td><%= route['time'] %></td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="databasetpl">
|
||||
<% if(ospfv3_database['scoped_link_db']) { %>
|
||||
<h2>{{ lang._('Scoped Link Database') }}</h2>
|
||||
<% _.each(_.keys(ospfv3_database['scoped_link_db']), function(areaname) { %>
|
||||
<% area = ospfv3_database['scoped_link_db'][areaname] %>
|
||||
<h3><% areaname %></h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="type" data-type="string">{{ lang._('Type') }}</th>
|
||||
<th data-column-id="lsid" data-type="string">{{ lang._('LS ID') }}</th>
|
||||
<th data-column-id="advrouter" data-type="string">{{ lang._('Advertising Router') }}</th>
|
||||
<th data-column-id="age" data-type="numeric">{{ lang._('Age') }}</th>
|
||||
<th data-column-id="seqnr" data-type="numeric">{{ lang._('Sequence Number') }}</th>
|
||||
<th data-column-id="payload" data-type="string">{{ lang._('Payload') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(area, function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry['Type'] %></td>
|
||||
<td><%= entry['LSId'] %></td>
|
||||
<td><%= entry['AdvRouter'] %></td>
|
||||
<td><%= entry['Age'] %></td>
|
||||
<td><%= entry['SeqNum'] %></td>
|
||||
<td><%= entry['Payload'] %></td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
<% if(ospfv3_database['if_scoped_link_state']) { %>
|
||||
<h2>{{ lang._('Interface Scoped Link Database') }}</h2>
|
||||
<% _.each(_.keys(ospfv3_database['if_scoped_link_state']), function(intfname) { %>
|
||||
<% intf = ospfv3_database['if_scoped_link_state'][intfname] %>
|
||||
<% _.each(_.keys(intf), function(areaname) { %>
|
||||
<% area = intf[areaname] %>
|
||||
<h3><%= intfname %> / <%= areaname %></h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="type" data-type="string">{{ lang._('Type') }}</th>
|
||||
<th data-column-id="lsid" data-type="string">{{ lang._('LS ID') }}</th>
|
||||
<th data-column-id="advrouter" data-type="string">{{ lang._('Advertising Router') }}</th>
|
||||
<th data-column-id="age" data-type="numeric">{{ lang._('Age') }}</th>
|
||||
<th data-column-id="seqnr" data-type="numeric">{{ lang._('Sequence Number') }}</th>
|
||||
<th data-column-id="payload" data-type="string">{{ lang._('Payload') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(area, function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry['Type'] %></td>
|
||||
<td><%= entry['LSId'] %></td>
|
||||
<td><%= entry['AdvRouter'] %></td>
|
||||
<td><%= entry['Age'] %></td>
|
||||
<td><%= entry['SeqNum'] %></td>
|
||||
<td><%= entry['Payload'] %></td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }) %>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
<% if (ospfv3_database['as_scoped']) { %>
|
||||
<h2>{{ lang._('AS Scoped') }}</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="type" data-type="string">{{ lang._('Type') }}</th>
|
||||
<th data-column-id="lsid" data-type="string">{{ lang._('LS ID') }}</th>
|
||||
<th data-column-id="advrouter" data-type="string">{{ lang._('Advertising Router') }}</th>
|
||||
<th data-column-id="age" data-type="numeric">{{ lang._('Age') }}</th>
|
||||
<th data-column-id="seqnr" data-type="numeric">{{ lang._('Sequence Number') }}</th>
|
||||
<th data-column-id="payload" data-type="string">{{ lang._('Payload') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% _.each(ospfv3_database['as_scoped'], function(entry) { %>
|
||||
<tr>
|
||||
<td><%= entry['Type'] %></td>
|
||||
<td><%= entry['LSId'] %></td>
|
||||
<td><%= entry['AdvRouter'] %></td>
|
||||
<td><%= entry['Age'] %></td>
|
||||
<td><%= entry['SeqNum'] %></td>
|
||||
<td><%= entry['Payload'] %></td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% } %>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="interfacetpl">
|
||||
<% _.each(_.keys(ospfv3_interface), function(interfacename) { %>
|
||||
<% int = ospfv3_interface[interfacename] %>
|
||||
<h2><%= interfacename %></h2>
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<% _.each(_.keys(int), function(propertyname) { %>
|
||||
<% if (propertyname != 'pending_lsas' ) { %>
|
||||
<tr>
|
||||
<td><%= translate(propertyname) %></td>
|
||||
<td>
|
||||
<% if (int[propertyname] === false || int[propertyname] === true) { %>
|
||||
<%= checkmark(int[propertyname]) %>
|
||||
<% } else if (propertyname == 'timers') { %>
|
||||
{{ lang._('Hello Timer:') }} <%= int[propertyname]['hello'] %><br />
|
||||
{{ lang._('Dead Timer:') }} <%= int[propertyname]['dead'] %><br />
|
||||
{{ lang._('Wait Timer:') }} <%= int[propertyname]['wait'] %><br />
|
||||
{{ lang._('Retransmit Timer:') }} <%= int[propertyname]['retransmit'] %>
|
||||
<% } else if (propertyname == 'IPv6' || propertyname == 'IPv4') { %>
|
||||
<%= _.join(int[propertyname],'<br />') %><br />
|
||||
<% } else if (propertyname == 'area_cost') { %>
|
||||
<% _.each(int[propertyname], function (ac) { %>
|
||||
<%= ac['area'] %>: <%= ac['cost'] %><br />
|
||||
<% }) %>
|
||||
<% } else { %>
|
||||
<%= translate(int[propertyname]) %>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<% } else { %>
|
||||
<% _.each(_.keys(int[propertyname]), function(lsa) { %>
|
||||
<% mylsa = int[propertyname][lsa] %>
|
||||
<tr>
|
||||
<td><%= lsa %> {{ lang._('Time') }}</td>
|
||||
<td><%= mylsa['time'] %> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><%= lsa %> {{ lang._('Count') }}</td>
|
||||
<td><%= mylsa['Count'] %> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><%= lsa %> {{ lang._('Flags') }}</td>
|
||||
<td><%= mylsa['flags'] %> </td>
|
||||
</tr>
|
||||
<% }) %>
|
||||
<% } %>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% }) %>
|
||||
</script>
|
||||
<script type="text/javascript" src="/ui/js/quagga/lodash.js"></script>
|
||||
<script>
|
||||
|
||||
function translate(data)
|
||||
{
|
||||
tr = []
|
||||
tr['count'] = '{{ lang._('Count') }}'
|
||||
tr['router'] = '{{ lang._('Router') }}'
|
||||
tr['network'] = '{{ lang._('Network') }}'
|
||||
tr['summary'] = '{{ lang._('Summary') }}'
|
||||
tr['ASBR summary'] = '{{ lang._('ASBR summary') }}'
|
||||
tr['NSSA'] = '{{ lang._('NSSA') }}'
|
||||
tr['directly attached'] = '{{ lang._('Directly Attached') }}'
|
||||
tr['Full/DR'] = '{{ lang._('Full (Designated Router)') }}'
|
||||
tr['enabled'] = '{{ lang._('Enabled') }}'
|
||||
tr['cost'] = '{{ lang._('Cost') }}'
|
||||
tr['priority'] = '{{ lang._('Priority') }}'
|
||||
tr['router_id'] = '{{ lang._('Router ID') }}'
|
||||
tr['network_type'] = '{{ lang._('Network Type') }}'
|
||||
tr['area'] = '{{ lang._('Area') }}'
|
||||
tr['transmit_delay'] = '{{ lang._('Transmit Delay') }}'
|
||||
tr['state'] = '{{ lang._('State') }}'
|
||||
tr['broadcast'] = '{{ lang._('Broadcast') }}'
|
||||
tr['mtu_mismatch_detection'] = '{{ lang._('MTU Mismatch Detection') }}'
|
||||
tr['address'] = '{{ lang._('Address') }}'
|
||||
tr['designated_router'] = '{{ lang._('Designated Router') }}'
|
||||
tr['designated_router_interface_address'] = '{{ lang._('Designated Router Interface Address') }}'
|
||||
tr['backup_designated_router'] = '{{ lang._('Backup Designated Router') }}'
|
||||
tr['multicast_group_memberships'] = '{{ lang._('Multicast Group Memberships') }}'
|
||||
tr['intervals'] = '{{ lang._('Intervals') }}'
|
||||
tr['hello_due_in'] = '{{ lang._('Hello Due In') }}'
|
||||
tr['neighbor_count'] = '{{ lang._('Neighbor Count') }}'
|
||||
tr['adjacent_neighbor_count'] = '{{ lang._('Adjacent Neighbor Count') }}'
|
||||
tr['timers'] = '{{ lang._('Timers') }}'
|
||||
tr['number_if_scoped_lsas'] = '{{ lang._('Number Of Interface Scoped LSAs') }}'
|
||||
tr['pending_lsas'] = '{{ lang._('Pending LSAs') }}'
|
||||
tr['area_cost'] = '{{ lang._('Area Cost') }}'
|
||||
tr['instance_id'] = '{{ lang._('Instance ID') }}'
|
||||
tr['interface_mtu'] = '{{ lang._('Interface MTU') }}'
|
||||
tr['type'] = '{{ lang._('Type') }}'
|
||||
tr['id'] = '{{ lang._('ID') }}'
|
||||
tr['up'] = '{{ lang._('Up') }}'
|
||||
tr['DR'] = '{{ lang._('Designated Router') }}'
|
||||
tr['BDR'] = '{{ lang._('Backup Designated Router') }}'
|
||||
tr['BROADCAST'] = '{{ lang._('Broadcast') }}'
|
||||
tr['UNKNOWN'] = '{{ lang._('Unknown') }}'
|
||||
tr['POINTOPOINT'] = '{{ lang._('Point to Point') }}'
|
||||
tr['LOOPBACK'] = '{{ lang._('Loopback') }}'
|
||||
return _.has(tr,data) ? tr[data] : data
|
||||
}
|
||||
|
||||
function checkmark(bin)
|
||||
{
|
||||
return "<i class=\"fa " + (bin ? "fa-check-square" : "fa-square") + " text-muted\"></i>";
|
||||
}
|
||||
|
||||
dataconverters = {
|
||||
boolean: {
|
||||
from: function (value) { return (value == 'true') || (value == true); },
|
||||
to: function (value) { return checkmark(value) }
|
||||
},
|
||||
raw: {
|
||||
from: function (value) { return value },
|
||||
to: function (value) { return value }
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status'])
|
||||
});
|
||||
|
||||
ajaxCall(url="/api/quagga/diagnostics/ospfv3overview", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#overviewtpl').html())(data['response'])
|
||||
$('#overview').html(content)
|
||||
});
|
||||
ajaxCall(url="/api/quagga/diagnostics/ospfv3database", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#databasetpl').html())(data['response'])
|
||||
$('#database').html(content)
|
||||
$('#database table').bootgrid()
|
||||
});
|
||||
ajaxCall(url="/api/quagga/diagnostics/ospfv3route", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#routestpl').html())(data['response'])
|
||||
$('#routing').html(content)
|
||||
$('#routing table').bootgrid()
|
||||
});
|
||||
/*ajaxCall(url="/api/quagga/diagnostics/ospfv3neighbor", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#neighbortpl').html())(data['response'])
|
||||
$('#neighbor').html(content)
|
||||
});*/
|
||||
ajaxCall(url="/api/quagga/diagnostics/ospfv3interface", sendData={}, callback=function(data,status) {
|
||||
content = _.template($('#interfacetpl').html())(data['response'])
|
||||
$('#interface').html(content)
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Navigation bar -->
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" href="#overview">{{ lang._('Overview') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#routing">{{ lang._('Routing Table') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#database">{{ lang._('Database') }}</a></li>
|
||||
<!--<li><a data-toggle="tab" href="#neighbor">{{ lang._('Neighbor') }}</a></li>-->
|
||||
<li><a data-toggle="tab" href="#interface">{{ lang._('Interface') }}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content content-box tab-content">
|
||||
<div id="overview" class="tab-pane fade in active">
|
||||
</div>
|
||||
<div id="routing" class="tab-pane fade in">
|
||||
</div>
|
||||
<div id="database" class="tab-pane fade in">
|
||||
</div>
|
||||
<div id="neighbor" class="tab-pane fade in">
|
||||
</div>
|
||||
<div id="interface" class="tab-pane fade in">
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
{#
|
||||
|
||||
OPNsense® is Copyright © 2014 – 2017 by Deciso B.V.
|
||||
This file is Copyright © 2017 by 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.
|
||||
|
||||
#}
|
||||
<div class="content-box" style="padding-bottom: 1.5em;">
|
||||
{{ partial("layout_partials/base_form",['fields':generalForm,'id':'frm_general_settings'])}}
|
||||
<hr />
|
||||
<div class="col-md-12">
|
||||
<button class="btn btn-primary" id="saveAct" type="button"><b>{{ lang._('Save') }}</b></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$( document ).ready(function() {
|
||||
var data_get_map = {'frm_general_settings':"/api/quagga/general/get"};
|
||||
mapDataToFormUI(data_get_map).done(function(data){
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
|
||||
// link save button to API set action
|
||||
$("#saveAct").click(function(){
|
||||
saveFormToEndpoint(url="/api/quagga/general/set", formid='frm_general_settings',callback_ok=function(){
|
||||
ajaxCall(url="/api/quagga/service/reconfigure", sendData={}, callback=function(data,status) {
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{ partial("layout_partials/base_form",['fields':generalForm,'id':'frm_ospf_settings'])}}
|
||||
23
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/log.volt
Normal file
23
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/log.volt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<div class="content-box">
|
||||
<table id="logtable" class="table table-condensed table-hover table-striped" style="table-layout: initial;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="date" data-sortable="false" data-type="string">{{ lang._('Date') }}</th>
|
||||
<th data-column-id="time" data-sortable="false" data-type="string">{{ lang._('Time') }}</th>
|
||||
<th data-column-id="service" data-sortable="false" data-type="string">{{ lang._('Service') }}</th>
|
||||
<th data-column-id="message" data-sortable="false" data-type="string">{{ lang._('Message') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$("#logtable").bootgrid({
|
||||
ajax: true,
|
||||
navigation: 0,
|
||||
url: "/api/quagga/diagnostics/log",
|
||||
ajaxSettings: { "method": "GET", cache: true },
|
||||
responseHandler: function(resp) { return {"rows": resp}; },
|
||||
sortable: false
|
||||
});
|
||||
</script>
|
||||
187
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/ospf.volt
Normal file
187
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/ospf.volt
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
{#
|
||||
|
||||
OPNsense® is Copyright © 2014 – 2017 by Deciso B.V.
|
||||
This file is Copyright © 2017 by 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.
|
||||
|
||||
#}
|
||||
|
||||
<!-- 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="#networks">{{ lang._('Networks') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#interfaces">{{ lang._('Interfaces') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#prefixlists">{{ lang._('Prefix Lists') }}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content content-box tab-content">
|
||||
<div id="general" class="tab-pane fade in active">
|
||||
<div class="content-box" style="padding-bottom: 1.5em;">
|
||||
{{ partial("layout_partials/base_form",['fields':generalForm,'id':'frm_ospf_settings'])}}
|
||||
|
||||
<div class="col-md-12">
|
||||
<hr />
|
||||
<button class="btn btn-primary" id="saveAct" type="button"><b>{{ lang._('Save') }}</b></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab: Networks -->
|
||||
<div id="networks" class="tab-pane fade in">
|
||||
<table id="grid-networks" class="table table-responsive" data-editDialog="DialogEditNetwork">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
|
||||
<th data-column-id="ipaddr" data-type="string" data-visible="true">{{ lang._('Network Address') }}</th>
|
||||
<th data-column-id="netmask" data-type="string" data-visible="true">{{ lang._('Mask') }}</th>
|
||||
<th data-column-id="area" data-type="string" data-visible="true">{{ lang._('Area') }}</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>
|
||||
|
||||
<!-- Tab: Interfaces -->
|
||||
<div id="interfaces" class="tab-pane fade in">
|
||||
<table id="grid-interfaces" class="table table-responsive" data-editDialog="DialogEditInterface">
|
||||
<thead>
|
||||
<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="networktype" data-type="string" data-visible="true">{{ lang._('Network Type') }}</th>
|
||||
<th data-column-id="authtype" data-type="string" data-visible="true">{{ lang._('Authentication 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>
|
||||
</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="DialogEditPrefixLists">
|
||||
<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>
|
||||
|
||||
<script type="text/javascript">
|
||||
$( document ).ready(function() {
|
||||
var data_get_map = {'frm_ospf_settings':"/api/quagga/ospfsettings/get"};
|
||||
mapDataToFormUI(data_get_map).done(function(data){
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
|
||||
// link save button to API set action
|
||||
$("#saveAct").click(function(){
|
||||
saveFormToEndpoint(url="/api/quagga/ospfsettings/set",formid='frm_ospf_settings',callback_ok=function(){
|
||||
ajaxCall(url="/api/quagga/service/reconfigure", sendData={}, callback=function(data,status) {
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
$("#grid-networks").UIBootgrid(
|
||||
{ 'search':'/api/quagga/ospfsettings/searchNetwork',
|
||||
'get':'/api/quagga/ospfsettings/getNetwork/',
|
||||
'set':'/api/quagga/ospfsettings/setNetwork/',
|
||||
'add':'/api/quagga/ospfsettings/addNetwork/',
|
||||
'del':'/api/quagga/ospfsettings/delNetwork/',
|
||||
'toggle':'/api/quagga/ospfsettings/toggleNetwork/',
|
||||
'options':{selection:false, multiSelect:false}
|
||||
}
|
||||
);
|
||||
$("#grid-interfaces").UIBootgrid(
|
||||
{ 'search':'/api/quagga/ospfsettings/searchInterface',
|
||||
'get':'/api/quagga/ospfsettings/getInterface/',
|
||||
'set':'/api/quagga/ospfsettings/setInterface/',
|
||||
'add':'/api/quagga/ospfsettings/addInterface/',
|
||||
'del':'/api/quagga/ospfsettings/delInterface/',
|
||||
'toggle':'/api/quagga/ospfsettings/toggleInterface/',
|
||||
'options':{selection:false, multiSelect:false}
|
||||
}
|
||||
);
|
||||
$("#grid-prefixlists").UIBootgrid(
|
||||
{ 'search':'/api/quagga/ospfsettings/searchPrefixlist',
|
||||
'get':'/api/quagga/ospfsettings/getPrefixlist/',
|
||||
'set':'/api/quagga/ospfsettings/setPrefixlist/',
|
||||
'add':'/api/quagga/ospfsettings/addPrefixlist/',
|
||||
'del':'/api/quagga/ospfsettings/delPrefixlist/',
|
||||
'toggle':'/api/quagga/ospfsettings/togglePrefixlist/',
|
||||
'options':{selection:false, multiSelect:false}
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEditNetwork,'id':'DialogEditNetwork','label':lang._('Edit Network')])}}
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEditInterface,'id':'DialogEditInterface','label':lang._('Edit Interface')])}}
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEditPrefixLists,'id':'DialogEditPrefixLists','label':lang._('Edit Prefix Lists')])}}
|
||||
113
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/ospf6.volt
Normal file
113
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/ospf6.volt
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
{#
|
||||
|
||||
OPNsense® is Copyright © 2014 – 2017 by Deciso B.V.
|
||||
This file is Copyright © 2017 by Fabian Franz
|
||||
This file is Copyright © 2017 by Michael Muenz
|
||||
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.
|
||||
|
||||
#}
|
||||
|
||||
<!-- 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="#interfaces">{{ lang._('Interfaces') }}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content content-box tab-content">
|
||||
<div id="general" class="tab-pane fade in active">
|
||||
<div class="content-box" style="padding-bottom: 1.5em;">
|
||||
{{ partial("layout_partials/base_form",['fields':ospf6Form,'id':'frm_ospf6_settings'])}}
|
||||
|
||||
<div class="col-md-12">
|
||||
<hr />
|
||||
<button class="btn btn-primary" id="saveAct" type="button"><b>{{ lang._('Save') }}</b></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab: Interfaces -->
|
||||
<div id="interfaces" class="tab-pane fade in">
|
||||
<table id="grid-interfaces" class="table table-responsive" data-editDialog="DialogEditInterface">
|
||||
<thead>
|
||||
<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="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>
|
||||
</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>
|
||||
|
||||
<script type="text/javascript">
|
||||
$( document ).ready(function() {
|
||||
var data_get_map = {'frm_ospf6_settings':"/api/quagga/ospf6settings/get"};
|
||||
mapDataToFormUI(data_get_map).done(function(data){
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
|
||||
// link save button to API set action
|
||||
$("#saveAct").click(function(){
|
||||
saveFormToEndpoint(url="/api/quagga/ospf6settings/set",formid='frm_ospf6_settings',callback_ok=function(){
|
||||
ajaxCall(url="/api/quagga/service/reconfigure", sendData={}, callback=function(data,status) {
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
$("#grid-interfaces").UIBootgrid(
|
||||
{ 'search':'/api/quagga/ospf6settings/searchInterface',
|
||||
'get':'/api/quagga/ospf6settings/getInterface/',
|
||||
'set':'/api/quagga/ospf6settings/setInterface/',
|
||||
'add':'/api/quagga/ospf6settings/addInterface/',
|
||||
'del':'/api/quagga/ospf6settings/delInterface/',
|
||||
'toggle':'/api/quagga/ospf6settings/toggleInterface/',
|
||||
'options':{selection:false, multiSelect:false}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEditInterface,'id':'DialogEditInterface','label':lang._('Edit Interface')])}}
|
||||
62
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/rip.volt
Normal file
62
net/frr/src/opnsense/mvc/app/views/OPNsense/Quagga/rip.volt
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{#
|
||||
|
||||
OPNsense® is Copyright © 2014 – 2017 by Deciso B.V.
|
||||
This file is Copyright © 2017 by 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.
|
||||
|
||||
#}
|
||||
<div class="content-box" style="padding-bottom: 1.5em;">
|
||||
{{ partial("layout_partials/base_form",['fields':ripForm,'id':'frm_rip_settings'])}}
|
||||
|
||||
<div class="col-md-12">
|
||||
<hr />
|
||||
<button class="btn btn-primary" id="saveAct" type="button"><b>{{ lang._('Save') }}</b></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
var data_get_map = {'frm_rip_settings':"/api/quagga/rip/get"};
|
||||
mapDataToFormUI(data_get_map).done(function(data){
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
|
||||
// link save button to API set action
|
||||
$("#saveAct").click(function(){
|
||||
saveFormToEndpoint(url="/api/quagga/rip/set",formid='frm_rip_settings',callback_ok=function(){
|
||||
ajaxCall(url="/api/quagga/service/reconfigure", sendData={}, callback=function(data,status) {
|
||||
ajaxCall(url="/api/quagga/service/status", sendData={}, callback=function(data,status) {
|
||||
updateServiceStatusUI(data['status']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
20
net/frr/src/opnsense/scripts/quagga/diag-bgp.sh
Executable file
20
net/frr/src/opnsense/scripts/quagga/diag-bgp.sh
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
case "$1" in
|
||||
bgp)
|
||||
vtysh -d bgpd -c "show ip bgp"
|
||||
;;
|
||||
summary)
|
||||
vtysh -d bgpd -c "show ip bgp summary"
|
||||
;;
|
||||
neighbor)
|
||||
vtysh -d bgpd -c "show ip bgp neighbors $2"
|
||||
;;
|
||||
neighbor-adv)
|
||||
vtysh -d bgpd -c "show ip bgp neighbors $2 advertised-routes"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 bgp|summary|neighbor <ip>|neighbor-adv <ip>"
|
||||
exit 1
|
||||
esac
|
||||
exit 0
|
||||
757
net/frr/src/opnsense/scripts/quagga/quagga.rb
Executable file
757
net/frr/src/opnsense/scripts/quagga/quagga.rb
Executable file
|
|
@ -0,0 +1,757 @@
|
|||
#!/usr/local/bin/ruby
|
||||
=begin
|
||||
Copyright 2017 Fabian Franz
|
||||
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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
=end
|
||||
|
||||
require 'json'
|
||||
require 'shellwords'
|
||||
require 'pp'
|
||||
|
||||
$QUAGGA_DEBUG = false
|
||||
|
||||
class VTYSH
|
||||
def initialize(path = '/usr/local/bin/vtysh')
|
||||
@path = path
|
||||
end
|
||||
|
||||
def execute(param)
|
||||
o = `#{@path} -c #{param.shellescape}`
|
||||
raise "error" if o.length <= 2
|
||||
raise "command error - command: #{param}" if o.include? "% Unknown command"
|
||||
o
|
||||
end
|
||||
|
||||
#def execute(param)
|
||||
# fn = param.sub("show","sh").gsub(" ","_")
|
||||
# File.read(fn)
|
||||
#end
|
||||
end
|
||||
|
||||
class QuaggaTableReader
|
||||
attr_accessor :headers
|
||||
def initialize(headers = [])
|
||||
@headers = headers
|
||||
end
|
||||
def read_headline(line, start_without_header = false, start_without_header_name = 'status')
|
||||
# get begin of header (number of the first char of the string)
|
||||
header = line
|
||||
header_offset = {}
|
||||
header_offset[0] = start_without_header_name if start_without_header
|
||||
@headers.map do |x|
|
||||
header_offset[header.index(x)] = x.strip
|
||||
end
|
||||
|
||||
|
||||
# make ranges: this will make a range of the first char of the sting until
|
||||
# the the char befor the next heading begins
|
||||
ranges = []
|
||||
0.upto (header_offset.keys.length - 2) do |i|
|
||||
ranges << ((header_offset.keys[i])...(header_offset.keys[i + 1]))
|
||||
end
|
||||
# the last one has no next heading - this will go to the end of the line
|
||||
ranges.push ((header_offset.keys.last)..-1) # path
|
||||
@header_offset = header_offset
|
||||
@ranges = ranges
|
||||
nil
|
||||
end
|
||||
|
||||
def read_entry(line, expand_fields = {})
|
||||
raise "heading missing" unless @ranges
|
||||
tmp = {}
|
||||
return tmp unless line&.strip.length > 2
|
||||
|
||||
@ranges.each do |r|
|
||||
# the string starts here
|
||||
b = r.begin
|
||||
# get the heading starting where the string starts
|
||||
n = @header_offset[b]
|
||||
# get the data or return an empty string
|
||||
tmp[n] = line[r]&.strip || ""
|
||||
end
|
||||
# replace characters by the meaning
|
||||
expand_fields.keys.each do |key|
|
||||
tmp[key] = tmp[key].split("").map {|x| {dn: expand_fields[key][x], abb: x} } if tmp[key]
|
||||
end
|
||||
tmp
|
||||
end
|
||||
end
|
||||
|
||||
class General
|
||||
def initialize(vtysh)
|
||||
@vtysh = vtysh
|
||||
end
|
||||
def routes(ipv6 = false)
|
||||
lines = @vtysh.execute("show ip#{ipv6 ? 'v6' : ''} route").lines
|
||||
|
||||
# headers
|
||||
meanings = {}
|
||||
while (line = lines.shift.strip) != ''
|
||||
line = line.gsub('Codes: ','')
|
||||
line.split(",").each do |meaning|
|
||||
short, long = meaning.strip.split(" - ")
|
||||
meanings[short] = long
|
||||
end
|
||||
end
|
||||
|
||||
# you don't have to understand this regex ;)
|
||||
entry_regex = /(\S+?)\s+?(\S+?)(?: \[(\d+)\/(\d+)\])? (?:via (\S+?)|is ([^,]+?)), ([^,\n]+)(?:, (\S+))?/
|
||||
entries = []
|
||||
while (line = lines.shift&.strip)
|
||||
if line.length > 10
|
||||
code, network, ad, metric, via, direct, interface, time = line.scan(entry_regex).first
|
||||
code = code.split('').map {|c| {short: c, long: meanings[c]}}
|
||||
entries << {code: code, network: (network || direct), ad: ad, via: via, metric: metric, interface: interface, time: time }
|
||||
end
|
||||
end
|
||||
entries
|
||||
end
|
||||
|
||||
def routes6
|
||||
routes(true)
|
||||
end
|
||||
|
||||
def log
|
||||
File.read('/var/log/frr.log').lines.select {|l| l.strip.length > 10}.map do |line|
|
||||
date, time, service, message = line.split(' ', 4)
|
||||
date = date.split('/').reverse.join(".") # format dd.mm.yyyy
|
||||
service = service.split(':').first if service
|
||||
{date: date, time:time, service: service, message: message }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class OSPF
|
||||
def initialize(vtysh)
|
||||
@vtysh = vtysh
|
||||
end
|
||||
def neighbors
|
||||
qta = QuaggaTableReader.new(["Neighbor ID", "Pri", "State", "Dead Time", "Address", "Interface", "RXmtL", "RqstL", "DBsmL"])
|
||||
lines = @vtysh.execute("show ip ospf neighbor").lines
|
||||
lines.shift # empty line
|
||||
data = []
|
||||
qta.read_headline(lines.shift)
|
||||
while (line = lines.shift) && (line.length > 2)
|
||||
data << qta.read_entry(line)
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
def interface
|
||||
lines = @vtysh.execute("show ip ospf interface").lines
|
||||
interfaces = {}
|
||||
current_if = ''
|
||||
while line = lines.shift
|
||||
next if line.strip.length <= 1
|
||||
if line[0] != ' ' # we are in a heading
|
||||
current_if = line.split(" ").first
|
||||
interfaces[current_if] = {}
|
||||
current_if = interfaces[current_if]
|
||||
current_if[:enabled] = true
|
||||
lines.shift
|
||||
else
|
||||
line.strip!
|
||||
case line
|
||||
when 'OSPF not enabled on this interface'
|
||||
current_if[:enabled] = false
|
||||
when /Internet Address ([^,]+?), Broadcast ([^,]+?), Area (.*)/
|
||||
current_if[:address] = $1
|
||||
current_if[:broadcast] = $2
|
||||
current_if[:area] = $3
|
||||
when /MTU mismatch detection:(.*)/
|
||||
current_if[:mtu_mismatch_detection] = ($1 == 'enabled')
|
||||
when /Router ID ([^,]+?), Network Type ([^,]+?), Cost: (\d+)/
|
||||
current_if[:router_id] = $1
|
||||
current_if[:network_type] = $2
|
||||
current_if[:cost] = $3.to_i
|
||||
when /Transmit Delay is (\d+) sec, State ([^,]+?), Priority (\d+)/
|
||||
current_if[:transmit_delay] = $1.to_i
|
||||
current_if[:state] = $2
|
||||
current_if[:priority] = $3.to_i
|
||||
when "No designated router on this network"
|
||||
current_if[:designated_router] = nil
|
||||
when /Designated Router \(ID\) ([^,]+?), Interface Address (.*)/
|
||||
current_if[:designated_router] = $1
|
||||
current_if[:designated_router_interface_address] = $2
|
||||
when "No backup designated router on this network"
|
||||
current_if[:backup_designated_router] = nil
|
||||
when /Timer intervals configured, Hello (\d+)s, Dead (\d+)s, Wait (\d+)s, Retransmit (\d+)/
|
||||
current_if[:intervals] = {hello: $1.to_i, dead: $2.to_i, wait: $3.to_i, retransmit: $4.to_i}
|
||||
when /Multicast group memberships: (.*)/
|
||||
current_if[:multicast_group_memberships] = $1.split(" ")
|
||||
when /Hello due in ([\d\.]+|inactive)s?/
|
||||
current_if[:hello_due_in] = $1 == 'inactive' ? $1 : $1.to_f
|
||||
when /Neighbor Count is (\d+), Adjacent neighbor count is (\d+)/
|
||||
current_if[:neighbor_count] = $1.to_i
|
||||
current_if[:adjacent_neighbor_count] = $2.to_i
|
||||
else
|
||||
# make sure there is an array to write in
|
||||
current_if[:unparsed] ||= []
|
||||
current_if[:unparsed] << line
|
||||
puts line if $QUAGGA_DEBUG
|
||||
end
|
||||
end
|
||||
end
|
||||
interfaces
|
||||
end
|
||||
|
||||
def database
|
||||
lines = @vtysh.execute("show ip ospf database").lines
|
||||
db = {}
|
||||
heading = ''
|
||||
router = ''
|
||||
router_link_states_area = ''
|
||||
mode = :none
|
||||
qta = nil
|
||||
while line = lines.shift
|
||||
next if line == ''
|
||||
if line[0] == ' ' # heading
|
||||
heading = line.strip
|
||||
case heading
|
||||
when /OSPF Router with ID \(([\.\d]+)\)/
|
||||
router = $1
|
||||
db[router] ||= {}
|
||||
mode = :router
|
||||
when /Router Link States \(Area ([\.\d]+)\)/
|
||||
router_link_states_area = $1
|
||||
db[router]['router_link_state_area'] ||= {}
|
||||
db[router]['router_link_state_area'][$1] ||= []
|
||||
mode = :router_link_state
|
||||
qta = nil
|
||||
when /Net Link States \(Area ([\.\d]+)\)/
|
||||
net_link_states_area = $1
|
||||
db[router]['net_link_state_area'] ||= {}
|
||||
db[router]['net_link_state_area'][$1] ||= []
|
||||
mode = :net_link_state
|
||||
qta = nil
|
||||
when 'AS External Link States'
|
||||
mode = :states
|
||||
db[router]['external_states'] ||= []
|
||||
qta = nil
|
||||
else
|
||||
puts "unknown heading" if $QUAGGA_DEBUG
|
||||
end
|
||||
else
|
||||
if qta == nil
|
||||
case mode
|
||||
when :router_link_state
|
||||
qta = QuaggaTableReader.new(["Link ID", "ADV Router", "Age", "Seq#", "CkSum", "Link count"])
|
||||
when :net_link_state
|
||||
qta = QuaggaTableReader.new(["Link ID", "ADV Router", "Age", "Seq#", "CkSum"])
|
||||
when :states
|
||||
qta = QuaggaTableReader.new(["Link ID", "ADV Router", "Age", "Seq#", "CkSum", "Route\n"])
|
||||
else
|
||||
next
|
||||
end
|
||||
headline = lines.shift
|
||||
qta.read_headline(headline,true)
|
||||
else
|
||||
entry = qta.read_entry(line)
|
||||
case mode
|
||||
when :router_link_state
|
||||
db[router]['router_link_state_area'][router_link_states_area] << entry
|
||||
when :net_link_state
|
||||
db[router]['net_link_state_area'][net_link_states_area] << entry
|
||||
when :states
|
||||
db[router]['external_states'] << entry
|
||||
end
|
||||
end
|
||||
end
|
||||
# table
|
||||
end
|
||||
db
|
||||
end
|
||||
|
||||
def route
|
||||
lines = @vtysh.execute("show ip ospf route").lines
|
||||
heading = ''
|
||||
route = {}
|
||||
last_line = []
|
||||
while line = lines.shift
|
||||
if line[0] == "=" #heading
|
||||
heading = line.scan(/=* ([^=]*) =*/).first.first
|
||||
route[heading] = []
|
||||
else # data
|
||||
case line.strip
|
||||
when /N\s+([\d\.\/]+)\s+\[(\d+)\]\s+area:\s(.*)/
|
||||
last_line = {network: $1, cost: $2.to_i, area: $3, type: 'N'}
|
||||
route[heading] << last_line
|
||||
when /N (E(?:\d+) (?:\S+))\s+\[([\d\/]+)\] tag: (\d+)/
|
||||
last_line = {network: $1, cost: $2, tag: $3.to_i, type: 'N'}
|
||||
route[heading] << last_line
|
||||
when /(?:(directly attached) to|via ([^,]+),) (.*)/
|
||||
last_line[:via] = $1 || $2
|
||||
last_line[:via_interface] = $3
|
||||
when /R\s+(\S+)\s+\[(\d+)\] area: ([^,]+)(, ASBR)/
|
||||
last_line = {ip: $1, cost: $2.to_i, area: $3, asbr: (", ASBR" == $4), type: 'R'}
|
||||
route[heading] << last_line
|
||||
else
|
||||
puts line if $QUAGGA_DEBUG
|
||||
end
|
||||
end
|
||||
end
|
||||
route
|
||||
end
|
||||
|
||||
def overview
|
||||
lines = @vtysh.execute("show ip ospf").lines
|
||||
overview = {rfc2328_conform: false, asbr: false}
|
||||
while line = lines.shift&.strip
|
||||
case line
|
||||
when /OSPF Routing Process, Router ID: ([\d\.]+)/
|
||||
overview[:router_id] = $1
|
||||
when "This implementation conforms to RFC2328"
|
||||
overview[:rfc2328_conform] = true
|
||||
when /OpaqueCapability flag is (\S+)/
|
||||
overview[:opaque_capability] = ($1 == 'enabled')
|
||||
when /Initial SPF scheduling delay (\d+) millisec\(s\)/
|
||||
overview[:initial_spf_scheduling_delay] = $1.to_i
|
||||
when /(Min|Max)imum hold time between consecutive SPFs (\d+) millisec\(s\)/
|
||||
overview[:hold_time] ||= {}
|
||||
overview[:hold_time][$1.downcase] = $2.to_i
|
||||
when "This router is an ASBR (injecting external routing information)"
|
||||
overview[:asbr] = true
|
||||
when /Number of external LSA (\d+). Checksum Sum ([x\d]+)/
|
||||
overview[:external_lsa] = {count: $1.to_i, checksum: $2}
|
||||
when /Number of opaque AS LSA (\d+). Checksum Sum ([x\d]+)/
|
||||
overview[:opaque_as_lsa] = {count: $1.to_i, checksum: $2}
|
||||
when /Refresh timer (\d+) secs/
|
||||
overview[:refresh_timer] = $1.to_i
|
||||
when /Number of areas attached to this router: (\d+)/
|
||||
overview[:areas_attached_count] = $1.to_i
|
||||
when /Hold time multiplier is currently (\d+)/
|
||||
overview[:current_hold_time_multipier] = $1.to_i
|
||||
when /RFC1583Compatibility flag is (\S+)/
|
||||
overview[:rfc1583_compatibility] = ($1 == 'enabled')
|
||||
when /SPF timer is (.*)/
|
||||
overview[:spf_timer] = $1
|
||||
when ""
|
||||
break
|
||||
else
|
||||
puts line if $QUAGGA_DEBUG
|
||||
end
|
||||
end
|
||||
# general overview has ended - now the area overviews come
|
||||
overview[:areas] = {}
|
||||
current_area = {}
|
||||
while line = lines.shift&.strip
|
||||
case line
|
||||
when /Area ID: (.*)/
|
||||
current_area = {}
|
||||
overview[:areas][$1] = current_area
|
||||
when /Number of interfaces in this area: Total: (\d+), Active: (\d+)/
|
||||
current_area[:interfaces] = {total: $1.to_i,active: $2.to_i}
|
||||
when /Number of (router|network|summary) LSA (\d+). Checksum Sum ([\da-fx]+)/
|
||||
current_area[:lsa] ||= {}
|
||||
current_area[:lsa][$1] = {count: $2.to_i, checksum: $3}
|
||||
when /Number of LSA (\d+)/
|
||||
current_area[:lsa] ||= {}
|
||||
current_area[:lsa][:count] = $1.to_i
|
||||
when /Number of (opaque (?:area|link)|NSSA|ASBR summary) LSA (\d+). Checksum Sum ([\da-fx]+)/
|
||||
current_area[:lsa] ||= {}
|
||||
current_area[:lsa][$1] = {count: $2.to_i, checksum: $3}
|
||||
when /Number of fully adjacent neighbors in this area: (\d+)/
|
||||
current_area[:fully_adjacent_neighbor_count] = $1.to_i
|
||||
when /SPF algorithm executed (\d) times/
|
||||
current_area[:spf_exec_count] = $1.to_i
|
||||
when "Area has no authentication"
|
||||
current_area[:auth] = "none"
|
||||
else
|
||||
puts line if $QUAGGA_DEBUG
|
||||
end
|
||||
end
|
||||
overview
|
||||
end
|
||||
end
|
||||
|
||||
class BGP
|
||||
def initialize(sh)
|
||||
@vtysh = sh
|
||||
end
|
||||
|
||||
def overview
|
||||
output = @vtysh.execute('show ip bgp')
|
||||
return {} if output.include? "No BGP process is configured"
|
||||
return {} unless output.include? 'version' # we get an empty output if quagga is not running
|
||||
output = output.split("\n")
|
||||
bgp = {}
|
||||
|
||||
x,y = output.shift.scan(/.*?version is (\d+).*?ID is ([0-9\.]+).*/).first
|
||||
bgp['table_version'] = x
|
||||
bgp['local_router_id'] = y
|
||||
|
||||
# find out, what the status abbreviations mean
|
||||
status_codes = {}
|
||||
line = output.shift
|
||||
line.split(":").last.strip.split(",").each do |x|
|
||||
k,v = x.strip.split(" ")
|
||||
status_codes[k] = v
|
||||
end
|
||||
while line.end_with? ","
|
||||
line = output.shift
|
||||
line.strip.split(",").each do |x|
|
||||
k,v = x.strip.split(" ")
|
||||
status_codes[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
# same like before but for the origin codes
|
||||
origin_codes = {}
|
||||
output.shift.split(":").last.strip.split(",").each do |x|
|
||||
k,v = x.strip.split(" - ")
|
||||
origin_codes[k] = v
|
||||
end
|
||||
|
||||
# drop empty line
|
||||
output.shift
|
||||
# read entries
|
||||
bgp['output'] = []
|
||||
qta = QuaggaTableReader.new(["Network", "Next Hop", "Metric", "LocPrf", "Weight", "Path"])
|
||||
qta.read_headline(output.shift,true)
|
||||
while line = output.shift&.strip
|
||||
break if line == ''
|
||||
data = qta.read_entry(line)
|
||||
data['status'] = data['status'].split("").map {|x| {dn: status_codes[x], abb: x} }
|
||||
data['Path'] = data['Path'].split("").map {|x| {dn: origin_codes[x], abb: x} }
|
||||
bgp['output'] << data
|
||||
end
|
||||
bgp
|
||||
end
|
||||
end
|
||||
|
||||
class OSPFv3
|
||||
def initialize(sh)
|
||||
@vtysh = sh
|
||||
end
|
||||
|
||||
def overview
|
||||
lines = @vtysh.execute("show ipv6 ospf6").lines
|
||||
overview = {}
|
||||
while line = lines.shift&.strip
|
||||
case line
|
||||
when /OSPFv3 Routing Process \((\d+)\) with Router-ID ([\d\.]+)/
|
||||
overview[:router_id] = $2
|
||||
overview[:routing_process] = $1.to_i
|
||||
when /Initial SPF scheduling delay (\d+) millisec\(s\)/
|
||||
overview[:initial_spf_scheduling_delay] = $1.to_i
|
||||
# this line contains a typo in the output - I made it to work with and without
|
||||
# this typo
|
||||
when /(Min|Max)imum hold time between consecutive SPFs (\d+) milli?second\(s\)/
|
||||
overview[:hold_time] ||= {}
|
||||
overview[:hold_time][$1.downcase] = $2.to_i
|
||||
when "This router is an ASBR (injecting external routing information)"
|
||||
overview[:asbr] = true
|
||||
when /SPF timer is (.*)/
|
||||
overview[:spf_timer] = $1
|
||||
when /Running (.*)/
|
||||
overview[:running_time] = $1
|
||||
when /Number of AS scoped LSAs is (\d+)/
|
||||
overview[:number_as_scoped] = $1.to_i
|
||||
when /Hold time multiplier is currently (\d+)/
|
||||
overview[:current_hold_time_multipier] = $1.to_i
|
||||
when /Number of areas in this router is (\d+)/
|
||||
overview[:number_of_areas] = $1.to_i
|
||||
when ""
|
||||
break
|
||||
else
|
||||
# debug
|
||||
puts line if $QUAGGA_DEBUG
|
||||
end
|
||||
end
|
||||
# general overview has ended - now the area overviews come
|
||||
overview[:areas] = {}
|
||||
current_area = {}
|
||||
while line = lines.shift&.strip
|
||||
case line
|
||||
when /^Area ([\d\.]*)/
|
||||
current_area = {}
|
||||
overview[:areas][$1] = current_area
|
||||
when /Interface attached to this area: (.*)/
|
||||
current_area[:interfaces] = $1.split(" ")
|
||||
when /Number of Area scoped LSAs is (.*)/
|
||||
current_area[:number_lsas] = $1.to_i
|
||||
else
|
||||
puts line if $QUAGGA_DEBUG
|
||||
end
|
||||
end
|
||||
overview
|
||||
end
|
||||
|
||||
def linkstate
|
||||
lines = @vtysh.execute("show ipv6 ospf6 linkstate").lines
|
||||
linkstate = {}
|
||||
|
||||
qta = nil
|
||||
current_area = []
|
||||
while line = lines.shift&.strip
|
||||
case line
|
||||
when /SPF Result in Area (.*)/
|
||||
linkstate[$1] = current_area = []
|
||||
qta = QuaggaTableReader.new(["Type","Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost"])
|
||||
lines.shift
|
||||
qta.read_headline(lines.shift)
|
||||
else
|
||||
if line.length > 10
|
||||
current_area << qta.read_entry(line)
|
||||
end
|
||||
end
|
||||
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,
|
||||
f2: f2,
|
||||
network: network,
|
||||
gateway: gateway,
|
||||
interface: interface,
|
||||
time: time }
|
||||
end
|
||||
route
|
||||
end
|
||||
|
||||
def neighbors
|
||||
qta = QuaggaTableReader.new(["Neighbor ID","Pri", "DeadTime", "State/IfState", "Duration I/F[State]"])
|
||||
neighbor = []
|
||||
nb = @vtysh.execute("show ipv6 ospf6 neighbor").lines
|
||||
qta.read_headline(nb.shift.strip)
|
||||
while line = nb.shift&.strip
|
||||
puts line
|
||||
if line.length > 10
|
||||
tmp = qta.read_entry(line)
|
||||
tmp['Pri'] = tmp['Pri'].to_i
|
||||
neighbor << tmp
|
||||
end
|
||||
end
|
||||
neighbor
|
||||
end
|
||||
def database
|
||||
lines = @vtysh.execute("show ipv6 ospf6 database").lines
|
||||
database = {}
|
||||
mode = :none
|
||||
area = ''
|
||||
qta = :none
|
||||
while line = lines.shift&.strip
|
||||
case line
|
||||
when /Area Scoped Link State Database \(Area (.*)\)/
|
||||
mode = :scoped_link_db
|
||||
database[:scoped_link_db] ||= {}
|
||||
database[:scoped_link_db][$1] = area = []
|
||||
qta = database_qta(lines)
|
||||
when /I\/F Scoped Link State Database \(I\/F (\S+) in Area (.*)\)/
|
||||
mode = :if_scoped_link_state
|
||||
database[:if_scoped_link_state] ||= {}
|
||||
database[:if_scoped_link_state][$1] ||= {}
|
||||
area = database[:if_scoped_link_state][$1][$2] ||= []
|
||||
qta= database_qta(lines)
|
||||
when "AS Scoped Link State Database"
|
||||
mode = :as_scoped
|
||||
area = database[:as_scoped] ||= []
|
||||
qta=database_qta(lines)
|
||||
# note: i have no data for this but i think it looks like the others
|
||||
else
|
||||
if line.length > 10
|
||||
area << qta.read_entry(line)
|
||||
end
|
||||
end
|
||||
end
|
||||
database
|
||||
end
|
||||
|
||||
def interface
|
||||
lines = @vtysh.execute("show ipv6 ospf6 interface").lines
|
||||
int = {}
|
||||
current_if = {}
|
||||
while line = lines.shift
|
||||
if line.length > 5
|
||||
case line.strip
|
||||
when /(\S+) is (down|up), type ([A-Z]+)/
|
||||
current_if = int[$1] = {up: ($2 == "up" ? true : false),
|
||||
type: $3,
|
||||
enabled: true}
|
||||
when /Interface ID: (\d+)/
|
||||
current_if[:id] = $1.to_i
|
||||
when /OSPF not enabled on this interface/
|
||||
current_if[:enabled] = false
|
||||
when /Instance ID (\d+), Interface MTU (\d+) \(autodetect: (\d+)\)/
|
||||
current_if[:instance_id] = $1.to_i
|
||||
current_if[:interface_mtu] = $2.to_i
|
||||
current_if[:interface_mtu_autodetect] = $3.to_i
|
||||
when "Internet Address:"
|
||||
# ignore
|
||||
when /(inet |inet6): (\S+)/
|
||||
current_if[:IPv6] ||= []
|
||||
current_if[:IPv4] ||= []
|
||||
family = $1 == 'inet6' ? :IPv6 : :IPv4
|
||||
address = $2
|
||||
current_if[family] << address
|
||||
when /MTU mismatch detection: (en|dis)abled/
|
||||
current_if[:mtu_mismatch_detection] = $1 == 'en'
|
||||
when /DR: (\S+) BDR: (\S+)/
|
||||
current_if[:designated_router] = $1
|
||||
current_if[:backup_designated_router] = $2
|
||||
when /State (\S+), Transmit Delay (\d+) sec, Priority (\d+)/
|
||||
current_if[:state] = $1
|
||||
current_if[:transmit_delay] = $2.to_i
|
||||
current_if[:priority] = $3.to_i
|
||||
when /Number of I\/F scoped LSAs is (\d+)/
|
||||
current_if[:number_if_scoped_lsas] = $1.to_i
|
||||
when /(\d+) Pending LSAs for (\S+) in Time ([\d:]+)(?: (.*))/
|
||||
current_if[:pending_lsas] ||= {}
|
||||
current_if[:pending_lsas][$2] = {time: $3,
|
||||
count: $1,
|
||||
flags: $4}
|
||||
when "Timer intervals configured:"
|
||||
# ignore
|
||||
when /Hello (\d+), Dead (\d+), Retransmit (\d+)/
|
||||
current_if[:timers] = {hello: $1.to_i,
|
||||
dead: $2.to_i,
|
||||
retransmit: $3.to_i }
|
||||
when /Area ID (\S+), Cost (\d+)/
|
||||
current_if[:area_cost] ||= []
|
||||
current_if[:area_cost] << {area: $1, cost: $2.to_i }
|
||||
else
|
||||
puts line if $QUAGGA_DEBUG
|
||||
end
|
||||
end
|
||||
end
|
||||
int
|
||||
end
|
||||
|
||||
private
|
||||
def database_qta(lines)
|
||||
# DON'T REMOVE THE SPACES!!!
|
||||
# For some reasons the fields are right aligned with the fields which makes it hard
|
||||
# to parse. I don't know a better way to get the correct offset except automatically.
|
||||
# (Detection of semantic of the fields)
|
||||
qta = QuaggaTableReader.new(["Type", "LSId", "AdvRouter", " Age", " SeqNum"," Payload"])
|
||||
lines.shift
|
||||
qta.read_headline(lines.shift)
|
||||
qta
|
||||
end
|
||||
end
|
||||
|
||||
require 'optparse'
|
||||
options = {}
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "Usage: #{__FILE__} -s section [section specific params]"
|
||||
#### OSPFv2
|
||||
opts.on("-d", "--ospf-database", "Prints the OSPF Database") do |od|
|
||||
options[:ospf_database] = od
|
||||
end
|
||||
opts.on("-r", "--ospf-route", 'print OSPF routing table') do |od|
|
||||
options[:ospf_route] = od
|
||||
end
|
||||
opts.on("-i", "--ospf-interface", 'print OSPF interface information') do |od|
|
||||
options[:ospf_interface] = od
|
||||
end
|
||||
opts.on("-n", "--ospf-neighbor", 'Print OSPF neighbors') do |od|
|
||||
options[:ospf_neighbors] = od
|
||||
end
|
||||
opts.on("-o", "--ospf-overview", "Print OSPF summary") do |od|
|
||||
options[:ospf_overview] = od
|
||||
end
|
||||
#### OSPFv3
|
||||
opts.on("-D", "--ospfv3-database", "Prints the OSPFv3 Database") do |od|
|
||||
options[:ospfv3_database] = od
|
||||
end
|
||||
opts.on("-t", "--ospfv3-route", 'print OSPFv3 routing table') do |od|
|
||||
options[:ospfv3_route] = od
|
||||
end
|
||||
opts.on("-I", "--ospfv3-interface", 'print OSPFv3 interface information') do |od|
|
||||
options[:ospfv3_interface] = od
|
||||
end
|
||||
opts.on("-N", "--ospfv3-neighbor", 'Print OSPFv3 neighbors') do |od|
|
||||
options[:ospfv3_neighbors] = od
|
||||
end
|
||||
opts.on("-O", "--ospfv3-overview", "Print OSPFv3 summary") do |od|
|
||||
options[:ospfv3_overview] = od
|
||||
end
|
||||
#### general things about routing
|
||||
opts.on("-R", "--general-routes", "Print Routing Table (IPv4)") do |od|
|
||||
options[:general_routes] = od
|
||||
end
|
||||
opts.on("-6", "--general-routes6", "Print Routing Table (IPv6)") do |od|
|
||||
options[:general_routes6] = od
|
||||
end
|
||||
opts.on("-l", "--general-log", "Print Logs") do |od|
|
||||
options[:general_log] = od
|
||||
end
|
||||
### BGP
|
||||
opts.on("-B", "--bgp-overview", "Print an overview of BGP") do |od|
|
||||
options[:bgp_overview] = od
|
||||
end
|
||||
### program opts
|
||||
opts.on("-H", "--human-readable", "Print the output human readable (not json)") do |od|
|
||||
options[:human_readable] = od
|
||||
end
|
||||
opts.on("-X", "--debug", "Prints debug output") do |od|
|
||||
$QUAGGA_DEBUG = true
|
||||
end
|
||||
opts.on("-h", "--help", "Prints this help") do
|
||||
puts opts
|
||||
exit
|
||||
end
|
||||
end.parse!
|
||||
# use the lib
|
||||
sh = VTYSH.new
|
||||
ospf = OSPF.new sh
|
||||
ospfv3 = OSPFv3.new sh
|
||||
bgp = BGP.new sh
|
||||
general = General.new sh
|
||||
|
||||
result = {}
|
||||
options.keys.each do |k|
|
||||
# if it is true
|
||||
if options[k]
|
||||
begin
|
||||
if k.to_s.include? 'ospf_'
|
||||
cmd = k.to_s.split('_').last
|
||||
result[k] = ospf.send(cmd)
|
||||
elsif k.to_s.include? 'ospfv3'
|
||||
cmd = k.to_s.split('_').last
|
||||
result[k] = ospfv3.send(cmd)
|
||||
elsif k.to_s.include? 'general'
|
||||
cmd = k.to_s.split('_').last
|
||||
result[k] = general.send(cmd)
|
||||
elsif k.to_s.include? 'bgp'
|
||||
cmd = k.to_s.split('_').last
|
||||
result[k] = bgp.send(cmd)
|
||||
end
|
||||
rescue # do nothing on an error
|
||||
result[k] = "error"
|
||||
puts $! if $QUAGGA_DEBUG
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# ospf.database, general.routes, ospf.interface, ospf.neighbors, ospf.route, ospf.overview
|
||||
if options[:human_readable]
|
||||
pp result
|
||||
else
|
||||
print result.to_json
|
||||
end
|
||||
20
net/frr/src/opnsense/scripts/quagga/setup.sh
Executable file
20
net/frr/src/opnsense/scripts/quagga/setup.sh
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
user=frr
|
||||
group=frr
|
||||
|
||||
mkdir -p /var/run/frr
|
||||
chown $user:$group /var/run/frr
|
||||
chmod 750 /var/run/frr
|
||||
|
||||
mkdir -p /usr/local/etc/frr
|
||||
chown $user:$group /usr/local/etc/frr
|
||||
chmod 750 /usr/local/etc/frr
|
||||
|
||||
# ensure that frr can read the configuration files
|
||||
chown -R $user:$group /usr/local/etc/frr
|
||||
chown -R $user:$group /var/run/frr
|
||||
|
||||
# logfile (if used)
|
||||
touch /var/log/frr.log
|
||||
chown $user:$group /var/log/frr.log
|
||||
125
net/frr/src/opnsense/service/conf/actions.d/actions_quagga.conf
Normal file
125
net/frr/src/opnsense/service/conf/actions.d/actions_quagga.conf
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
[start]
|
||||
command:/usr/local/opnsense/scripts/quagga/setup.sh;/usr/local/etc/rc.d/frr start
|
||||
parameters:
|
||||
type:script
|
||||
message:starting quagga
|
||||
|
||||
[stop]
|
||||
command:/usr/local/etc/rc.d/frr stop; exit 0
|
||||
parameters:
|
||||
type:script
|
||||
message:stopping quagga
|
||||
|
||||
[restart]
|
||||
command:/usr/local/opnsense/scripts/quagga/setup.sh;/usr/local/etc/rc.d/frr restart
|
||||
parameters:
|
||||
type:script
|
||||
message:restarting quagga
|
||||
|
||||
[reconfigure]
|
||||
command:/usr/local/opnsense/scripts/quagga/setup.sh;/usr/local/etc/rc.d/frr reload
|
||||
parameters:
|
||||
type:script
|
||||
message:reconfigure quagga
|
||||
|
||||
[status]
|
||||
command:/usr/local/etc/rc.d/frr status;exit 0
|
||||
parameters:
|
||||
type:script_output
|
||||
message:request quagga
|
||||
|
||||
[diag-bgp]
|
||||
command:/usr/local/opnsense/scripts/quagga/diag-bgp.sh
|
||||
parameters:%s
|
||||
type:script_output
|
||||
message:bgp diagnostics
|
||||
|
||||
[diag-bgp2]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --bgp-overview
|
||||
parameters:
|
||||
type:script_output
|
||||
message:bgp diagnostics
|
||||
|
||||
[ospf-database]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospf-database
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Shows the OSPF database
|
||||
|
||||
[ospf-route]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospf-route
|
||||
parameters:
|
||||
type:script_output
|
||||
message: print OSPF routing table
|
||||
|
||||
[ospf-interface]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospf-interface
|
||||
parameters:
|
||||
type:script_output
|
||||
message: print OSPF interface information
|
||||
|
||||
[ospf-neighbor]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospf-neighbor
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Print OSPF neighbors
|
||||
|
||||
[ospf-overview]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospf-overview
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Print OSPF summary
|
||||
|
||||
[ospfv3-database]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospfv3-database
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Shows the OSPF database
|
||||
|
||||
[ospfv3-route]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospfv3-route
|
||||
parameters:
|
||||
type:script_output
|
||||
message: print OSPF routing table
|
||||
|
||||
[ospfv3-interface]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospfv3-interface
|
||||
parameters:
|
||||
type:script_output
|
||||
message: print OSPF interface information
|
||||
|
||||
[ospfv3-neighbor]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospfv3-neighbor
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Print OSPF neighbors
|
||||
|
||||
[ospfv3-overview]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --ospfv3-overview
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Print OSPF summary
|
||||
|
||||
[general-routes]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --general-routes
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Print IPv4 Routing Table
|
||||
|
||||
[general-routes6]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --general-routes6
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Print IPv6 Routing Table
|
||||
|
||||
[general-log]
|
||||
command:/usr/local/opnsense/scripts/quagga/quagga.rb --general-log
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Show Quagga logs
|
||||
|
||||
[general-runningconfig]
|
||||
command:/usr/local/bin/vtysh -c "show run"
|
||||
parameters:
|
||||
type:script_output
|
||||
message: Show running configuration
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
bgpd.conf:/usr/local/etc/frr/bgpd.conf
|
||||
ospfd.conf:/usr/local/etc/frr/ospfd.conf
|
||||
ospf6d.conf:/usr/local/etc/frr/ospf6d.conf
|
||||
ripd.conf:/usr/local/etc/frr/ripd.conf
|
||||
frr:/etc/rc.conf.d/frr
|
||||
zebra.conf:/usr/local/etc/frr/zebra.conf
|
||||
118
net/frr/src/opnsense/service/templates/OPNsense/Quagga/bgpd.conf
Normal file
118
net/frr/src/opnsense/service/templates/OPNsense/Quagga/bgpd.conf
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
{% if helpers.exists('OPNsense.quagga.bgp.enabled') and OPNsense.quagga.bgp.enabled == '1' %}
|
||||
{% from 'OPNsense/Macros/interface.macro' import physical_interface %}
|
||||
!
|
||||
! Zebra configuration saved from vty
|
||||
! 2017/03/03 20:21:04
|
||||
!
|
||||
{% if helpers.exists('OPNsense.quagga.general') %}
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablelogfile') and OPNsense.quagga.general.enablelogfile == '1' %}
|
||||
log file /var/log/frr.log {{ OPNsense.quagga.general.logfilelevel }}
|
||||
{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablesyslog') and OPNsense.quagga.general.enablesyslog == '1' %}
|
||||
log syslog {{ OPNsense.quagga.general.sysloglevel }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
!
|
||||
!
|
||||
!
|
||||
{% if helpers.exists('OPNsense.quagga.bgp.asnumber') and OPNsense.quagga.bgp.asnumber != '' %}
|
||||
router bgp {{ OPNsense.quagga.bgp.asnumber }}
|
||||
{% if helpers.exists('OPNsense.quagga.bgp.networks') %}
|
||||
{% for network in OPNsense.quagga.bgp.networks.split(',') %}
|
||||
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' %}
|
||||
neighbor {{ neighbor.address }} remote-as {{ neighbor.remoteas }}
|
||||
{% if 'updatesource' in neighbor and neighbor.updatesource != '' %}
|
||||
neighbor {{ neighbor.address }} update-source {{ physical_interface(neighbor.updatesource) }}
|
||||
{% endif %}
|
||||
{% if 'nexthopself' in neighbor and neighbor.nexthopself == '1' %}
|
||||
neighbor {{ neighbor.address }} next-hop-self
|
||||
{% endif %}
|
||||
{% 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
|
||||
!
|
||||
{% endif %}
|
||||
18
net/frr/src/opnsense/service/templates/OPNsense/Quagga/frr
Normal file
18
net/frr/src/opnsense/service/templates/OPNsense/Quagga/frr
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
defaultrouter="NO"
|
||||
frr_enable="{% if helpers.exists('OPNsense.quagga.general.enabled') and OPNsense.quagga.general.enabled == '1' %}YES{% else %}NO{% endif %}"
|
||||
|
||||
{% if helpers.exists('OPNsense.quagga.general.enabled') and OPNsense.quagga.general.enabled == '1' %}
|
||||
frr_opnsense_bootup_run="/usr/local/opnsense/scripts/quagga/setup.sh"
|
||||
{% endif %}
|
||||
|
||||
frr_daemons="zebra{%
|
||||
if helpers.exists('OPNsense.quagga.ospf.enabled') and OPNsense.quagga.ospf.enabled == '1' %} ospfd{% endif %}{%
|
||||
if helpers.exists('OPNsense.quagga.rip.enabled') and OPNsense.quagga.rip.enabled == '1' %} ripd{% endif %}{%
|
||||
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.isis.enabled') and OPNsense.quagga.isis.enabled == '1' %} isisd{% endif %}"
|
||||
#frr_flags="...."
|
||||
#frr_extralibs_path="... ..."
|
||||
#router_enable="NO"
|
||||
watchfrr_enable="YES"
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
{% macro cline(directive, modelname) -%}{% if modelname %}
|
||||
ipv6 ospf6 {{ directive }} {{ modelname }}
|
||||
{% endif %}{%- endmacro %}
|
||||
{% from 'OPNsense/Macros/interface.macro' import physical_interface %}
|
||||
{% if helpers.exists('OPNsense.quagga.ospf6.enabled') and OPNsense.quagga.ospf6.enabled == '1' %}
|
||||
!
|
||||
! Zebra configuration saved from vty
|
||||
! 2017/03/03 20:21:04
|
||||
!
|
||||
{% if helpers.exists('OPNsense.quagga.general') %}
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablelogfile') and OPNsense.quagga.general.enablelogfile == '1' %}
|
||||
log file /var/log/frr.log {{ OPNsense.quagga.general.logfilelevel }}
|
||||
{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablesyslog') and OPNsense.quagga.general.enablesyslog == '1' %}
|
||||
log syslog {{ OPNsense.quagga.general.sysloglevel }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
!
|
||||
!
|
||||
!
|
||||
{% if helpers.exists('OPNsense.quagga.ospf6.interfaces.interface') %}
|
||||
{% for interface in helpers.toList('OPNsense.quagga.ospf6.interfaces.interface') %}
|
||||
{% if interface.enabled == '1' %}
|
||||
interface {{ physical_interface(interface.interfacename) }}
|
||||
{{ cline("cost",interface.cost)
|
||||
}}{{ cline("dead-interval",interface.deadinterval)
|
||||
}}{{ cline("hello-interval",interface.hellointerval)
|
||||
}}{{ cline("priority",interface.priority)
|
||||
}}{{ cline("retransmit-interval",interface.retransmitinterval)
|
||||
}}!
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
!
|
||||
router ospf6
|
||||
{% if helpers.exists('OPNsense.quagga.ospf6.redistribute') and OPNsense.quagga.ospf6.redistribute != '' %}
|
||||
{% for line in OPNsense.quagga.ospf6.redistribute.split(',') %}
|
||||
redistribute {{ line }}
|
||||
{% endfor %}{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.ospf6.interfaces.interface') %}
|
||||
{% for interface in helpers.toList('OPNsense.quagga.ospf6.interfaces.interface') %}
|
||||
{% if interface.enabled == '1' %}
|
||||
interface {{ physical_interface(interface.interfacename) }} area {{ interface.area }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.ospf6.routerid') and OPNsense.quagga.ospf6.routerid != '' %}
|
||||
router-id {{ OPNsense.quagga.ospf6.routerid }}
|
||||
{% endif %}
|
||||
!
|
||||
line vty
|
||||
!
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
{% macro cline(directive, modelname) -%}{% if modelname %}
|
||||
ip ospf {{ directive }} {{ modelname }}
|
||||
{% endif %}{%- endmacro %}
|
||||
{% from 'OPNsense/Macros/interface.macro' import physical_interface %}
|
||||
{% if helpers.exists('OPNsense.quagga.ospf.enabled') and OPNsense.quagga.ospf.enabled == '1' %}
|
||||
!
|
||||
! Zebra configuration saved from vty
|
||||
! 2017/03/03 20:21:04
|
||||
!
|
||||
{% if helpers.exists('OPNsense.quagga.general') %}
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablelogfile') and OPNsense.quagga.general.enablelogfile == '1' %}
|
||||
log file /var/log/frr.log {{ OPNsense.quagga.general.logfilelevel }}
|
||||
{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablesyslog') and OPNsense.quagga.general.enablesyslog == '1' %}
|
||||
log syslog {{ OPNsense.quagga.general.sysloglevel }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
!
|
||||
!
|
||||
!
|
||||
{% if helpers.exists('OPNsense.quagga.ospf.interfaces.interface') %}
|
||||
{% for interface in helpers.toList('OPNsense.quagga.ospf.interfaces.interface') %}
|
||||
{% if interface.enabled == '1' %}
|
||||
interface {{ physical_interface(interface.interfacename) }}
|
||||
{{ cline("authentication",interface.authtype)
|
||||
}}{% if interface.authtype and interface.authtype == 'message-digest'
|
||||
%}{{ cline("message-digest-key 1 md5",interface.authkey)
|
||||
}}{% endif
|
||||
%}{{ cline("cost",interface.cost)
|
||||
}}{{ cline("dead-interval",interface.deadinterval)
|
||||
}}{{ cline("hello-interval",interface.hellointerval)
|
||||
}}{{ cline("priority",interface.priority)
|
||||
}}{{ cline("retransmit-interval",interface.retransmitinterval)
|
||||
}}!
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
!
|
||||
router ospf
|
||||
{% if helpers.exists('OPNsense.quagga.ospf.routerid') and OPNsense.quagga.ospf.routerid != '' %}
|
||||
ospf router-id {{ OPNsense.quagga.ospf.routerid }}
|
||||
{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.ospf.redistribute') and OPNsense.quagga.ospf.redistribute != '' %}
|
||||
{% for line in OPNsense.quagga.ospf.redistribute.split(',') %}
|
||||
redistribute {{ line }}
|
||||
{% endfor %}{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.ospf.passiveinterfaces') and OPNsense.quagga.ospf.passiveinterfaces != '' %}
|
||||
{% for line in OPNsense.quagga.ospf.passiveinterfaces.split(',') %}
|
||||
passive-interface {{ physical_interface(line) }}
|
||||
{% endfor %}{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.ospf.networks.network') %}
|
||||
{% for network in helpers.toList('OPNsense.quagga.ospf.networks.network') %}
|
||||
{% if network.enabled == '1' %}
|
||||
network {{ network.ipaddr }}/{{ network.netmask }} area {{ network.area }}
|
||||
{% endif %}
|
||||
{% if network.linkedPrefixlistIn|default("") != "" %}
|
||||
{% for prefixlist in network.linkedPrefixlistIn.split(",") %}
|
||||
{% set prefixlist2_data = helpers.getUUID(prefixlist) %}
|
||||
{% if prefixlist2_data != {} and prefixlist2_data.enabled == '1' %}
|
||||
area {{ network.area }} filter-list prefix {{ prefixlist2_data.name }} in
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if network.linkedPrefixlistOut|default("") != "" %}
|
||||
{% for prefixlist in network.linkedPrefixlistOut.split(",") %}
|
||||
{% set prefixlist_data = helpers.getUUID(prefixlist) %}
|
||||
{% if prefixlist_data != {} and prefixlist_data.enabled == '1' %}
|
||||
area {{ network.area }} filter-list prefix {{ prefixlist_data.name }} out
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.ospf.originate') and OPNsense.quagga.ospf.originate == '1' %}
|
||||
default-information originate{% if helpers.exists('OPNsense.quagga.ospf.originatealways') and OPNsense.quagga.ospf.originatealways == '1' %} always {% endif %}
|
||||
|
||||
{% endif %}
|
||||
!
|
||||
{% if helpers.exists('OPNsense.quagga.ospf.prefixlists.prefixlist') %}
|
||||
{% for prefixlist in helpers.sortDictList(OPNsense.quagga.ospf.prefixlists.prefixlist, 'name', 'seqnumber' ) %}
|
||||
{% if prefixlist.enabled == '1' %}
|
||||
ip prefix-list {{ prefixlist.name }} seq {{ prefixlist.seqnumber }} {{ prefixlist.action }} {{ prefixlist.network }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
!
|
||||
line vty
|
||||
!
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
{% if helpers.exists('OPNsense.quagga.rip.enabled') and OPNsense.quagga.rip.enabled == '1' %}
|
||||
{% from 'OPNsense/Macros/interface.macro' import physical_interface %}
|
||||
!
|
||||
! Zebra configuration saved from vty
|
||||
! 2017/03/26 22:40:16
|
||||
!
|
||||
{% if helpers.exists('OPNsense.quagga.general') %}
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablelogfile') and OPNsense.quagga.general.enablelogfile == '1' %}
|
||||
log file /var/log/frr.log {{ OPNsense.quagga.general.logfilelevel }}
|
||||
{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablesyslog') and OPNsense.quagga.general.enablesyslog == '1' %}
|
||||
log syslog {{ OPNsense.quagga.general.sysloglevel }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
!
|
||||
router rip
|
||||
version {{ OPNsense.quagga.rip.version }}
|
||||
{% if helpers.exists('OPNsense.quagga.rip.redistribute') and OPNsense.quagga.rip.redistribute != '' %}
|
||||
{% for line in OPNsense.quagga.rip.redistribute.split(',') %}
|
||||
redistribute {{ line }}
|
||||
{% endfor %}{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.rip.networks') %}
|
||||
{% for network in OPNsense.quagga.rip.networks.split(',') %}
|
||||
network {{ network }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.rip.passiveinterfaces') and OPNsense.quagga.rip.passiveinterfaces != '' %}
|
||||
{% for line in OPNsense.quagga.rip.passiveinterfaces.split(',') %}
|
||||
passive-interface {{ physical_interface(line) }}
|
||||
{% endfor %}{% endif %}
|
||||
!
|
||||
line vty
|
||||
!
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{% if helpers.exists('OPNsense.quagga.general') %}
|
||||
!
|
||||
! Zebra configuration saved from vty
|
||||
! 2017/03/03 20:21:04
|
||||
!
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablelogfile') and OPNsense.quagga.general.enablelogfile == '1' %}
|
||||
log file /var/log/frr.log {{ OPNsense.quagga.general.logfilelevel }}
|
||||
{% endif %}
|
||||
{% if helpers.exists('OPNsense.quagga.general.enablesyslog') and OPNsense.quagga.general.enablesyslog == '1' %}
|
||||
log syslog {{ OPNsense.quagga.general.sysloglevel }}
|
||||
{% endif %}
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
ip forwarding
|
||||
ipv6 forwarding
|
||||
!
|
||||
!
|
||||
line vty
|
||||
!
|
||||
{% endif %}
|
||||
17084
net/frr/src/opnsense/www/js/quagga/lodash.js
Normal file
17084
net/frr/src/opnsense/www/js/quagga/lodash.js
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue