diff --git a/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/Api/BgpController.php b/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/Api/BgpController.php new file mode 100644 index 000000000..c4d8fa5ea --- /dev/null +++ b/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/Api/BgpController.php @@ -0,0 +1,200 @@ +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" ) + ); + } + + 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) { + // save config if validated correctly + $mdlBGP->serializeToConfig(); + Config::getInstance()->save(); + $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 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'); + } +} diff --git a/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/BgpController.php b/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/BgpController.php index 4c9ed1657..8a46d369c 100644 --- a/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/BgpController.php +++ b/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/BgpController.php @@ -1,12 +1,34 @@ view->title = gettext("BGP-Settings"); - $this->view->generalForm = $this->getForm("bgp"); + $this->view->title = gettext("BGP Settings"); + $this->view->bgpForm = $this->getForm("bgp"); + $this->view->formDialogEditBGPNeighbor = $this->getForm("dialogEditBGPNeighbor"); $this->view->pick('OPNsense/Quagga/bgp'); } } diff --git a/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/bgp.xml b/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/bgp.xml index 194badc6d..a6ee35c6d 100644 --- a/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/bgp.xml +++ b/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/bgp.xml @@ -1,8 +1,30 @@
- routing.bgp.general.Enabled + bgp.enabled checkbox This will activate the bgp service. + + bgp.asnumber + + text + Your AS Number here + + + bgp.networks + + + select_multiple + true + Select the network to advertise, you have to set a Null route via System -> Routes + + + bgp.redistribute + + select_multiple + + + Type or select a route source. +
diff --git a/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPNeighbor.xml b/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPNeighbor.xml new file mode 100644 index 000000000..34139c884 --- /dev/null +++ b/net/quagga/src/opnsense/mvc/app/controllers/OPNsense/Quagga/forms/dialogEditBGPNeighbor.xml @@ -0,0 +1,35 @@ +
+ + neighbor.enabled + + checkbox + + + neighbor.address + + text + Specify the IP of your neighbor. + + + neighbor.remoteas + + text + Neighbor AS. + + + neighbor.updatesource + + text + Physical name of the interface facing the peer + + + neighbor.nexthopself + + checkbox + + + neighbor.defaultoriginate + + checkbox + +
diff --git a/net/quagga/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.php b/net/quagga/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.php new file mode 100644 index 000000000..9ebad2ea2 --- /dev/null +++ b/net/quagga/src/opnsense/mvc/app/models/OPNsense/Quagga/BGP.php @@ -0,0 +1,28 @@ + + //OPNsense/quagga/bgp + BGP Routing configuration + + + 0 + Y + + + + Y + + + + N + /^(\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})$/ + + + N + Y + + + Babel routing protocol (Babel) + Open Shortest Path First (OSPF) + Connected routes (directly attached subnet or host) + Intermediate System to Intermediate System (IS-IS) + Kernel routes (not installed via the zebra RIB) + Protocol Independent Multicast (PIM) + Routing Information Protocol (RIP) + Statically configured routes + + + + + + 1 + Y + +
+ + Y + /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ +
+ + + Y + + + + N + + + 0 + N + + + 0 + N + +
+
+
+ diff --git a/net/quagga/src/opnsense/mvc/app/models/OPNsense/Quagga/Menu/Menu.xml b/net/quagga/src/opnsense/mvc/app/models/OPNsense/Quagga/Menu/Menu.xml index 542de374c..1e31ab0e3 100644 --- a/net/quagga/src/opnsense/mvc/app/models/OPNsense/Quagga/Menu/Menu.xml +++ b/net/quagga/src/opnsense/mvc/app/models/OPNsense/Quagga/Menu/Menu.xml @@ -3,8 +3,8 @@ - + + diff --git a/net/quagga/src/opnsense/mvc/app/views/OPNsense/Quagga/bgp.volt b/net/quagga/src/opnsense/mvc/app/views/OPNsense/Quagga/bgp.volt index 4ca174841..db270a717 100644 --- a/net/quagga/src/opnsense/mvc/app/views/OPNsense/Quagga/bgp.volt +++ b/net/quagga/src/opnsense/mvc/app/views/OPNsense/Quagga/bgp.volt @@ -1 +1,104 @@ -{{ partial("layout_partials/base_form",['fields':generalForm,'id':'frm_ospf_settings'])}} +{# + +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':bgpForm,'id':'frm_bgp_settings'])}} + + + + +
+ +
+ +

{{ lang._('Neighbors') }}

+
+
+ + + + + + + + + + + + + + + + + + + + + + +
{{ lang._('Enabled') }}{{ lang._('Neighbor Address') }}{{ lang._('Remote AS') }}{{ lang._('Update Source Address') }}{{ lang._('Next Hop Self') }}{{ lang._('Default Originate') }}{{ lang._('ID') }}{{ lang._('Commands') }}
+ + +
+ +
+
+ +{{ partial("layout_partials/base_dialog",['fields':formDialogEditBGPNeighbor,'id':'DialogEditBGPNeighbor','label':'Edit Neighbor'])}} diff --git a/net/quagga/src/opnsense/service/templates/OPNsense/Quagga/+TARGETS b/net/quagga/src/opnsense/service/templates/OPNsense/Quagga/+TARGETS index b85dce436..0ad27b58a 100644 --- a/net/quagga/src/opnsense/service/templates/OPNsense/Quagga/+TARGETS +++ b/net/quagga/src/opnsense/service/templates/OPNsense/Quagga/+TARGETS @@ -1,3 +1,4 @@ +bgpd.conf:/usr/local/etc/quagga/bgpd.conf ospfd.conf:/usr/local/etc/quagga/ospfd.conf ripd.conf:/usr/local/etc/quagga/ripd.conf quagga:/etc/rc.conf.d/quagga diff --git a/net/quagga/src/opnsense/service/templates/OPNsense/Quagga/bgpd.conf b/net/quagga/src/opnsense/service/templates/OPNsense/Quagga/bgpd.conf new file mode 100644 index 000000000..084040e65 --- /dev/null +++ b/net/quagga/src/opnsense/service/templates/OPNsense/Quagga/bgpd.conf @@ -0,0 +1,36 @@ +{% if helpers.exists('OPNsense.quagga.bgp.enabled') and OPNsense.quagga.bgp.enabled == '1' %} +! +! Zebra configuration saved from vty +! 2017/03/03 20:21:04 +! +! +! +! +{% 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.neighbors.neighbor') %} +{% for neighbor in helpers.toList('OPNsense.quagga.bgp.neighbors.neighbor') %} +{% if neighbor.enabled == '1' %} + neighbor {{ neighbor.address }} remote-as {{ neighbor.remoteas }} +{% if helpers.exists('OPNsense.quagga.bgp.neighbors.neighbor.updatesource') and OPNsense.quagga.bgp.neighbors.neighbor.updatesource != '' %} + neighbor {{ neighbor.address }} update-source {{ neighbor.updatesource }} +{% endif %} +{% if neighbor.nexthopself == '1' %} + neighbor {{ neighbor.address }} next-hop-self +{% endif %} +{% if neighbor.defaultoriginate == '1' %} + neighbor {{ neighbor.address }} default-originate +{% endif %} +{% endif %} +{% endfor %} +{% endif %} +{% endif %} +! +line vty +! +{% endif %}