bird-openwrt: update to version 0.3

Enhancements and bug fixes including:
- Developed and Tested against Bird-1.6.3
- New LUCI scripts (Logs, Functions and Filters)
- Enhanced UX and less use of Terminal for daily management
- Improved UX by adding extra information for the administrator
- Refactor DOCN and include missing parts.
- Code cleaning and refactoring
- New DOCN-specific [Repository](https://github.com/eloicaso/bgp-bmx6-bird-docn)
This commit is contained in:
Eloi 2017-12-13 21:52:59 +00:00 committed by Moritz Warning
parent e35a8f9dc9
commit 7cb7b83325
36 changed files with 3367 additions and 1651 deletions

View File

@ -1,531 +0,0 @@
---------------------------------------------------------------------
Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
BGP/Bird integration with OpenWRT
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---------------------------------------------------------------------
*** Original documentation for BIRD Daemon can be found here: http://bird.network.cz/?get_doc
*** Some interesting examples are placed in BIRD daemon Gitlab page: https://gitlab.labs.nic.cz/labs/bird/wikis/home
*** If you want to add new options to bird*-openwrt packages,
*** feel free to make a pull request it in: https://github.com/openwrt-routing/packages/bird-openwrt
*** or email me and ask for it: eloicaso@openmailbox.org
- Options used in /etc/config/birdX -
---------------------------------------------------------------------
CONFIGURATION SECTION 1: 'bird'
---------------------------------------------------------------------
Example
--
config bird 'bird'
option use_UCI_config '1'
option UCI_config_file '/tmp/bird4.conf'
--
* use_UCI_config: Boolean
This option allows you to use UCI configuration translation file instead of the original Bird one. If true/1, birdX init.d script will use the translation placed in "UCI_config_file". Otherwise, it will use the default "/etc/birdX.conf" configuration.
[Hint] This could be used to allow multiple configurations and swap them easily.
Default: 0
* UCI_config_file: String (File path)
This option sets where will be placed the translation of the UCI configuration file.
Default: /tmp/birdX.conf
---------------------------------------------------------------------
CONFIGURATION SECTION 2: 'global NAME'
---------------------------------------------------------------------
Example
--
config global 'global'
option log_file '/tmp/bird4.log'
option log 'all'
option debug 'off'
option router_id '172.16.1.6'
--
* log_file: String (File path)
This option sets the path of the file used to save Bird Log and Debug's information.
Default: /tmp/birdX.log
* log: String/Enumeration (all/off, info, warning, error, fatal, debug, trace, remote, auth, bug)
This option allows you to set which information you want to save in the
[HINT] Use the enumeration like: { info, waning, error }
Default: all
* debug: String/Enumeration ( all/off, states, routes, filters, interfaces, events, packets)
This option allows you to set which debug information will be saved in the "log_file" file.
[HINT] Use the enumeration like: { info, waning, error }
Default: off
* router_id: IP Address
This option sets which will be the Router ID. Usually is the lowest IP address (not loopback) among the existing interfaces.
[HINT] In IPv4 this field is optional. In IPv6 is mandatory.
* listen_bgp_addr: IP Address
This option sets the IP address that Bird BGP instances will listen by default.
Default: 0.0.0.0
* listen_bgp_port: Integer (Port)
This option sets the port that Bird BGP instances will listen by default.
Default: 179
[IPv6 only]
* listen_bgp_dual: Boolean
This option sets if Bird6 BGP instances will listen only to IPv6 or IPv4/6 BGP routes.
---------------------------------------------------------------------
CONFIGURATION SECTION 3: 'table'
---------------------------------------------------------------------
Example
--
config table
option name 'aux'
--
* name: String
This option allows you to set the name of the auxiliar kernel tables used for Bird.
---------------------------------------------------------------------
CONFIGURATION SECTION 4: 'kernel NAME'
---------------------------------------------------------------------
Example
--
config kernel kernel1
option table 'aux'
option import 'all'
option export 'all'
option kernel_table '100'
option scan_time '10'
option learn '1'
option persist '0'
option disabled '0'
--
* table: String
Set an auxiliary table for the current kernel routing instance. This table MUST exist as a SECTION 3 instance.
[HINT] If there is an Kernel protocol instance that uses the "main" kernel table (not using table/kernel_table options), this should be included before the rest of Kernel instances (which will use auxiliary tables).
* import: String/Filter function
This option delimits which routes coming from other protocols will be accepted. This option allows filters in different manners:
1. All/none: allows to import all the routes or none of them.
2. Filter name: [import 'bgp_filter_in'] the protocol will use the filter with the Filter name. (Needs an existing filter declared in the UCI configuration file)
* export: String/Filter function
This option delimits which routes going out from the protocol. This option allows filters in different manners:
1. All/none: allows to export all the routes or none of them.
2. Filter name: [export 'bgp_filter_out'] the protocol will use the filter with the 'Filter name'. (Needs an existing filter declared in the UCI configuration file)
* kernel_table: Integer
This option sets the identification number of the Kernel table that will be used instead of the main one.
Default: main table (254)
* scan_time: Integer
This option sets the time between checks to the selected kernel table.
* learn: Boolean
Set if the kernel table will add the routes from other routing protocols or the system administrator.
* persist: Boolean
Set if Bird Daemon will save the known routes when exiting or if it will clean the routing table.
* disable: Boolean
This option sets if the protocol will be used or dismissed.
Default: 0
---------------------------------------------------------------------
CONFIGURATION SECTION 5: 'device NAME'
---------------------------------------------------------------------
Example
--
config device device1
option scan_time '10'
option disabled '0'
--
* scan_time: Integer
This option sets the time between checks to the selected kernel table.
* disable: Boolean
This option sets if the protocol will be used or dismissed.
Default: 0
CONFIGURATION SECTION 6: 'static NAME'
Example
--
config static static1
option table 'aux'
option disabled '0'
--
* table: String
Set an auxiliary table for the current static instance. This table MUST exist as a SECTION 3 instance.
[HINT] If there is an static instance that uses the "main" kernel table (not using table/kernel_table options), this should be included before the rest of static instances (which will use auxiliary tables).
* disable: Boolean
This option sets if the protocol will be used or dismissed.
Default: 0
---------------------------------------------------------------------
CONFIGURATION SECTION 7 & 8: 'bgp NAME' & 'bgp_template NAME'
---------------------------------------------------------------------
This section merges two different configuration sections: bgp instances and templates. The first one is the basic bgp configuration part and the second one is the template used to minimize the number of options written in the configuration file. Both configuration sections has the same options, but when Bird found duplicities, the bgp instance has priority over the template.
Examples
-- instance --
config bgp bgp1
option template 'bgp_common'
option description 'Description of the BGP instance'
option neighbor_address '172.16.1.5'
option neighbor_as '65530'
option source_address '172.16.1.6'
option next_hop_self '0'
option next_hop_keep '0'
option rr_client '1'
option rr_cluster_id '172.16.1.6'
--
-- template --
config bgp_template bgp_common
option table 'aux'
option import 'all'
option export 'all'
option local_address '172.16.1.6'
option local_as '65001'
option import_limit '100'
option import_limit_action 'warn'
option export_limit '100'
option export_limit_action 'warn'
option receive_limit '100'
option receive_limit_action 'warn'
option disabled '0'
--
* template: String
This option states the template used for current BGP instance. This template MUST exist as a SECTION 8 instance.
* description: String
This option allows to add a description of the bgp instance and its function
* local_addr: IP address
This optional option allows to set the IP source of our Autonomous System (AS).
* local_as: Integer
This option allows to set the identification number of our AS number. This option is mandatory for each BGP instance.
* neighbor_addr: IP address
Each BGP instance has a neighbor connected to. This option allows to set its IP address
* neighbor_as: Integer
Each BGP instance has a neighbor connected to. This option allows to set its AS ID.
* next_hop_self: Boolean
If this option is true, BGP protocol will avoid to calculate the next hop and always advertise own "Router id" IP .
Default: 0
* next_hop_keep: Boolean
If this option is true, BGP will always use the received next_hop information to redirect the route.
Default: 0
* rr_client: Boolean
IF this option is true, the router will be set as Route Reflector and will treat the rest of the routers as RR clients.
Default: 0
* rr_cluster_id: Integer
This option sets the identification number of the RR cluster. All the nodes in a cluster needs this option and share the same number.
Default: Router id
* import_limit: Integer
This option sets the limit of routes that a protocol can import until take the action indicated in the import_limit_action.
import_limit also counts filtered routes (even dropped).
Default: 0 (no limit)
* import_limit_action: String
This option allows to decide the action to take when reached the limit of imported routes.
Actions are: warn, block, restart, disable
* export_limit: Integer
This option sets the limit of routes that a protocol can export until take the action indicated in the export_limit_action.
Default: 0 (no limit)
* export_limit_action: String
This option allows to decide the action to take when reached the limit of exported routes.
Actions are: warn, block, restart, disable
* receive_limit: Integer
This option sets the limit of routes that a protocol can receive until take the action indicated in the receive_limit_action. receive_limit only counts accepted routes from the protocol.
Default: 0 (no limit)
* receive_limit_action: String
This option allows to decide the action to take when reached the limit of received routes.
Actions are: warn, block, restart, disable
* disable: Boolean
This option sets if the protocol will be used or dismissed.
Default: 0
---------------------------------------------------------------------
CONFIGURATION SECTION 9: 'route'
---------------------------------------------------------------------
Example
--
config route
option instance 'static1'
option type 'router'
option prefix '192.168.9.0/24'
option via '10.99.105.159'
config route
option instance 'static1'
option type 'special'
option prefix '192.168.2.0/24'
option attribute 'unreachable'
config route
option instance 'static1'
option type 'iface'
option prefix '192.168.3.0/24'
option iface 'mgmt0'
config route
option instance 'static1'
option type 'recursive'
option prefix '192.168.4.0/24'
option ip '192.168.1.1'
config route
option instance 'static1'
option type 'multipath'
option prefix '192.168.30.0/24'
list l_via '172.16.1.5'
list l_via '172.16.1.6'
--
* instance: String
This option indicates the route that the static protocol instance will apply.
* type: String
This option states the type of route that will be applied. Also defines the options available for it.
Types are: 'router', 'special', 'iface', 'recursive' or 'multipath'.
* prefix: IP address/network
This option allows to define the network that you want to define.
[router only]
* via: IP Address
This option indicates the IP address of the neighbor router where the routes will pass through.
[special only]
* attribute: String
This option will mark the behaviour of the route.
Attribures are: 'blackhole', 'unreachable' or 'prohibit'.
[iface only]
* iface: String
This option indicates the interface used to redirect the BGP routes. Careful, the interface MUST exist, or Bird will fail to start.
[recursive only]
* ip: IP address
This option states the IP address which the next hop will depend on.
[multipath only][This is a list, not an option. Use it as in the example, or check the UCI configuration documentation.]
* l_via: IP address
This list of IPs specifies the list (following the sequence) of routers that the route will follow as next hops.
---------------------------------------------------------------------
CONFIGURATION SECTION 10: 'filter NAME'
---------------------------------------------------------------------
Filters are written in separated files. Its syntax can be found in http://bird.network.cz/?get_doc&f=bird-5.html
The content of each filter file is copied in the birdX.conf file without checking its syntax.
Example
--
config filter 'firstFilter'
option type 'bgp'
option instance 'bgp1'
option file_path '/var/filters/f1'
--
* type: String
The type indicates to which routing protocol is the filter directed to. Currently only BGP is available.
* instance: String
This option indicates the filter that the routing protocol instance will apply.
* file_path: String (File path)
This option specifies the path to the filter file to be used in the routing protocol.
---------------------------------------------------------------------
COMPLETE CONFIGURATION EXAMPLE:
---------------------------------------------------------------------
config bird 'bird'
option use_UCI_config '1'
#Caution! Enabling this option, Bird will translate this
#UCI file and use it instead of /etc/bird4.conf
option UCI_config_file '/tmp/bird4.conf'
#If you enable useUCIconfig, UCIconfigFile will be Bird's
#configuration file location.
config global 'global'
option log_file '/tmp/bird4.log'
option log 'all'
option debug 'off'
option router_id '172.16.1.6'
config table
option name 'aux'
config kernel kernel1
option table 'aux'
option import 'all'
option export 'all'
option kernel_table '100'
option scan_time '10'
option learn '1'
option persist '0'
option disabled '0'
config device device1
option scan_time '10'
option disabled '0'
config static static1
option table 'aux'
option disabled '0'
config bgp bgp1
option template 'bgp_common'
option description 'Description of the BGP instance'
option neighbor_address '172.16.1.5'
option neighbor_as '65530'
option source_address '172.16.1.6'
option next_hop_self '0'
option next_hop_keep '0'
option rr_client '1'
option rr_cluster_id '172.16.1.6'
config bgp_template bgp_common
option table 'aux'
option import 'all'
option export 'all'
option local_address '172.16.1.6'
option local_as '65001'
option import_limit '100'
option import_limit_action 'warn'
option export_limit '100'
option export_limit_action 'warn'
option receive_limit '100'
option receive_limit_action 'warn'
option disabled '0'
#config ospf ospf1
# option cfg1583compat '1'
#
#config ospf_area '0.0.0.0'
# option instance 'ospf1'
# option stub '0'
#
#config ospf_interface '*'
# option area '0.0.0.0'
# option cost '100'
# option type 'broadcast'
# option hello '5'
# option password '1'
#
#config ospf_password '1'
# option authentication 'cryptographic'
# option passphrase '1234'
#
#config ospf_networks
# option area '0.0.0.0'
# list prefix '10.0.0.0/24'
#
#config ospf_hidden_networks
# option area '0.0.0.0'
# option prefix '12.0.0.0/24'
#
#config ospf_stubnet '11.0.0.0/24'
# option area '0.0.0.0'
# option hidden '0'
# option summary '0'
# option cost '101'
#
config route
option instance 'static1'
option type 'router'
option prefix '192.168.9.0/24'
option via '10.99.105.159'
config route
option instance 'static1'
option type 'special'
option prefix '192.168.2.0/24'
option attribute 'unreachable'
config route
option instance 'static1'
option type 'iface'
option prefix '192.168.3.0/24'
option iface 'mgmt0'
config route
option instance 'static1'
option type 'recursive'
option prefix '192.168.4.0/24'
option ip '192.168.1.1'
config route
option instance 'static1'
option type 'multipath'
option prefix '192.168.30.0/24'
list l_via '172.16.1.5'
list l_via '172.16.1.6'
config filter 'firstFilter'
option type 'bgp'
option instance 'bgp1'
option file_path '/var/filters/f1'

View File

@ -0,0 +1,342 @@
<!--
---------------------------------------------------------------------
(C) 2014 - 2017 Eloi Carbo <eloicaso@openmailbox.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---------------------------------------------------------------------
-->
# LUCI Bird{4|6} v0.3 Packages Documentation
* BIRD Daemon's official documentation: http://bird.network.cz/?get_doc
* Extra documentation in English & Catalan: https://github.com/eloicaso/bgp-bmx6-bird-docn
* If you want to add new options to bird*-openwrt packages add a pull request or issue in: https://github.com/eloicaso/bird-openwrt
> *Clarification*: This documentation covers luci-app-bird{4|6} as both are completely aligned and only those IPv4/6-specific options will be covered separately.
>
> Bird v1.6.3 has been used to test luci-app-bird{4|6}. Using newer versions of the Daemon might change the behaviour or messages documented here. Create an issue or pull request if you spot any mismatch in this document to address it.
# Table of contents
1. [Status Page](#status)
2. [Log Page](#log)
3. [Overview Page](#overview)
4. [General Protocols Page](#general)
5. [BGP Portocol](#bgp)
6. [Filters and Functions](#fnf)
## Status Page <a name="status"></a>
The Status Page allows you to Start, Stop and restart the service as well as to check the result of these operations.
#### Components
- *Button* **Start**: Execute a Bird Daemon Service Start call. Operation's result is shown in the *Service Status* Text Box.
- *Button* **Stop**: Execute a Bird Daemon Service Stop call. Operation's result is shown in the *Service Status* Text Box.
- *Button* **Restart**: Execute a Bird Daemon Service Restart call. Operation's result is shown in the *Service Status* Text Box.
- *Text Box* **Service Status**: Executes a Bird Daemon Service Status call. Operation's result is shown as plain text.
#### Service Status common messages
* *Running*: Service is running with no issues
* *Already started*: You have clicked *Start* when the service was already running. No action taken.
* *Stopped*: You have clicked *Stop* when the service was running. Service has been stopped.
* *Already stopped*: You have clicked *Stop* when the service was already stopped. No action taken.
* *Stopped ... Started*: You have pressed *Restart* when the service was running. The service has been restarted.
* *Already stopped .. Started*: You have pressed *Restart* when the service was already stopped. The service has been started.
* *Failed - ERROR MESSAGE*: There is a configuration or validation issue that prevents Bird to start. Check the *Error Message* and the Log Page to debug it and fix it.
#### Error Examples
1. Validation issues:
`bird4: Failed - bird: /tmp/bird4.conf, line 65: syntax error`
If we check the file shown: `/tmp/bird4.conf` :
```
protocol bgp BGPExample {
import Filter NonExistingFilter;
}
```
We have entered an invalid (non-existent in this case) filter name. In order to fix this, write the correct Filter Name or remove its reference from the BGP Protocol Configuration Page and start the service again.
2. Configuration issues:
` bird4: Failed - bird: /tmp/bird4.conf, line 76: Only internal neighbor can be RR client`
In this case, it is easy to spot that we have incorrectly selected the *Route Reflector Server* option incorrectly and we only need to untick it and start the service to solve it.
Usuarlly, any configuration issue will be flagged appropiately through Bird service messages. However, in the event where you do not have enough information, please look for advice in either Bird's documentation or in the affected Protocol's documentation.
## Log Page <a name="log"></a>
The Log Page shows the last 30 lines of the configured Bird Daemon Log file. This information is automatically refreshed each second.
#### Components
- *Text Area* **Log File**: 30 lines text area that shows the Log file information
- *Text* **Using Log File** and **File Size**: The first line of the Text Area is fixed and shows the file being used and its current size. **Please**, check this size information regularly to avoid letting the Log information overflow your Storage as it will make your service stop and prevent it to start until you fix it.
- *Text* **File Contents**: The next 30 lines show information about the events and debug information happening live. Main information are state changes and *info, warning, fatal or trace*. If you hit any issue starting the service, you can investigate the issue from this page.
## Overview Page <a name="overview"></a>
The Overview Page includes the configuration of basic Bird Daemon settings such as UCI usage, Routing Tables definition and Global Options.
### Bird File Settings (UCI Usage)
This section enables/disables the use of this package's capabilities.
#### Components
- *Check Box* **Use UCI configuration**:
- If enabled, the package will use the UCI configuration generated by this web settings and translate it into a Bird Daemon configuration file.
- If disabled, the package will do nothing and you will have to manually edit a Bird Daemon configuration file.
- *Text Box* **UCI File**: This file specifies the selected location for the translated Bird Daemon configuration file. Do not leave blank.
### Tables Configuration
This section allows you to set the Routing tables that will be used later in the different protocols. You can *Add* as many instances as required.
#### Components
- *Text Box* **Table Name**: Set an unique (meaningful) routing table name.
> In some instances or protocols, you may want or be required to set a specific ID to a Table. In order to do this, please, follow this -right now- [manual procedure](https://github.com/eloicaso/bgp-bmx6-bird-docn/blob/master/EN/manual_procedures.md).
### Global Options
This section allows you to configure basic Bird Daemon settings.
#### Components
- *Text Box* **Router ID**: Set the Identificator to be used in this Bird Daemon instance. This option must be:
> IPv4, this option will be set by default to the lowest IP Address configured. Otherwise, the identificator must be an IPv4 address.
> IPv6, this option is **mandatory** and must be a HEX value (Hexadecimal). This package (bird6-uci), provides the HEX value *0xCAFEBABE* as a default value to avoid initial crashes.
- *Text Box* **Log File**: Set the Name and Location of the Log file. By default, its location will be /tmp/bird{4|6}.log as the non-persistent partition.
- *Mutiple Value* **Log**: Set which elements you want Bird Daemon to log in the configured file.
> *Caution I*: if you select *All*, the other selected options will have no validity as, by definition, they are already included.
> *Caution II*: Take into consideration that the more elements Bird has to log, the more space you will require to store this log file. If your storage is full, Bird will fail to start until you free some space to store its Log data.
- *Multi Value* **Debug**: Set which Debug information elements you want Bird Daemon to log in the configured file.
> *Caution I*: if you select *All*, the other selected options will have no validity as, by definition, they are already included.
> *Caution II*: Take into consideration that the more elements Bird has to log, the more space you will require to store this log file (this is particularly critical in Debug as it can log MegaBytes of data quickly). If your storage is full, Bird will fail to start until you free some space to store its Log data.
## General Protocols <a name="general"></a>
The General Protocols Page includes the configuration of key OS Protocols or Network Basic Settings such as Kernel, Device or Static Routes.
### Kernel Options
This section allows you to set all the Kernel Protocols required to do Networking.
> The first Kernel instance is the Primary one and must be left by default for OS usage. Do not set its "Table" or "Kernel Table" options.
#### Components
- *Check Box* **Disabled**: Set this Check Box if you do not want to configure and use this Protocol.
- *List Value* **Table**: Select the Routing Table to be used in the Kernel Protocol instance.
> The Primary Kernel Protocol cannot be empty.
- *Text Box* **Import**: Set if the protocol must import routes and which ones.
- **all**: Accept all the incoming routes.
- **none**: Reject all the incoming routes.
- **filter filterName**: Call an existing filter to define which incoming routes will be accepted or rejected.
- *Text Box* **Export**: Set if the protocol must export routes and which ones.
- **all**: Accept all the outgoing routes.
- **none**: Reject all the outgoing routes.
- **filter filterName**: Call an existing filter to define which outgoing routes will be accepted or rejected.
- *Text Box* **Scan time**: Set the time between Kernel Routing Table scans. This value must be the same for all the Kernel Protocols.
- *Check Box* **Learn**: Set this option to allow the Kernel Protocol to learn Routes form other routing daemons or manually added by an admin.
- *Check Box* **Persist**: Set this option to store the routes learnt in the table until it is removed. Unset this option if you want to clean the routes on the fly.
- *Text Box* **Kernel Table**: Select the specific exitisting Routing Table for this Protocol instance.
> The Kernel Table ID must be previously set by the administrator during the Routing Table configuration. Currently (v0.3), this process is done manually. Please, follow this [manual procedure](https://github.com/eloicaso/bgp-bmx6-bird-docn/blob/master/EN/manual_procedures.md).
### Device Options
This section allows you to set all the Device *Protocol*. The Device *Protocol* is just a mechanism to bound the interfaces and Kernel tables in order to get its information.
#### Components
- *Check Box* **Disabled**: Set this Check Box if you do not want to configure and use this Protocol.
- *Text Box* **Scan Time**: Set the time between Kernel Routing Table scans. This value must be the same for all the Kernel Protocols.
### Static Options
This section allows you to create the container for Routes definition. Static protocol instances allows you to manually create Routes that Bird will use and which Routing Table should hold this information. It also helps to manage routes by marking them (i.e. *Unreachable*, *Blocked*, ...).
#### Components
- *Check Box* **Disabled**: Set this Check Box if you do not want to configure and use this Protocol.
- *List Value* **Table**: Select the Routing Table to be used in the Static Protocol instance.
### Routes
This section allows to set which Routes will be set in a specific Static Protocol and how these should be handled.
#### Components
- *List Value* **Route Instance**: Set which Static Protocol instance will contain this route infromation.
> Routes require an existing Static Protocol as parent.
- *Text Box* **Route Prefix**: Set the Route instance to be defined.
> Examples of routes are:. 10.0.0.0/8 (IPv4) or 2001:DB8:3000:0/16 (IPv6)
- *List Value* **Type Of Route**: This value will set the conditional settings. Options are:
- **Router**: Classic routes going through specific IP Addresses.
- *Text Box* **Via**: Set the target IP Address to be used for Routing
> I.e. 10.0.0.0/8 via 10.1.1.1
- **MultiPath**: Multiple paths Route.
- *List of Text Box* **Via**: Set the target Route to be used for Routing. This option allows several instances of **Via** elements.
> I.e. 10.0.0.0/8 via 10.1.1.1
> via 10.1.1.100
> via 10.1.1.200
- **Special**: Special treated Route.
- *Text Box* **Attribute**: Block special consideration of routes.
> **unreachable**: Return route cannot be reached.
> **prohibit**: Return route has been administratively blocked.
> **blackhole**: Silently drop the route.
- **Iface**: Classic routes going through specific interfaces.
- *List Value* **Interface**: Select the target interface to route.
- **Recursive**: Set a static recursive route. Its next hope will depen on the table's lookup for each target IP Address.
### Direct Protocol
This section allows to set pools of *directly* connected interfaces. Direct Protocol instances will make use of the *Device* Protocol in order to generate routes between the selected interfaces.
#### Components
- *Check Box* **Disabled**: Set this Check Box if you do not want to configure and use this Protocol.
- *Text Box* **Interfaces**: This is the key option allowing to *tie* the interfaces and create direct routes between different sides. Enter each interface's name you want to couple.
- If you leave this option empty, it will tie all the interfaces together.
- Each interface must be quoted: i.e. `"eth0"`
- Several interfaces must be entered comma-separated: i.e. `"eth0", "wlan0"`
- If you want to restrict this to specific interfaces, you have to enter them using its name or a pattern: i.e. All the ethernet interfaces `"eth*"`
- You are allowed to **exclude** specific interfaces by adding `-` before the interface name: i.e. Exclude all the Wireless interfaces `"-wlan*"`
> Example: All the wired interfaces (eth and em) but exclude all the wireless and point-to-point interfaces: `"eth*", "em*", "-wlan*", "-ptp_*"`
> Current version 0.3 requires you to enter each interface you want to **include** or **exclude** manually. This will be enhanced in future versions.
### Pipe Protocol
This section allows to set instances of *linked* routing tables. Each instance will allow you to share the routes from a primary table to a secondary one.
#### Components
- *Check Box* **Disabled**: Set this Check Box if you do not want to configure and use this Protocol.
- *List Value* **Table**: Select the **Primary** Routing Table to be used.
- *List Value* **Peer Table**: Select the **Secondary** Routing Table to be used.
- *List Value* **Mode**: Set if you want to work in *transparent* or *opaque* mode.
- **Transparent**: Retransmits all the routes and its attributes. Therefore, you get two identical routing tables. This is the default behaviour.
- **Opaque**: This mode is not recommended for new configurations and it is not recommended. Tables will only share the optimal routes and overwrite route's attributes with new ones (Pipe).
- *Text Box* **Import**: Set if the protocol must import routes and which ones.
- **all**: Accept all the incoming routes.
- **none**: Reject all the incoming routes.
- **filter filterName**: Call an existing filter to define which incoming routes will be accepted or rejected.
- *Text Box* **Export**: Set if the protocol must export routes and which ones.
- **all**: Accept all the outgoing routes.
- **none**: Reject all the outgoing routes.
- **filter filterName**: Call an existing filter to define which outgoing routes will be accepted or rejected.
## BGP Protocol<a name="bgp"></a>
The BGP Protocol Page includes all the settings to configure BGP Templates and BGP instances.
BGP Templates and Instances share most of the options as Templates are meant to diminish the requirements on Instances.
> An extreme example case could be the Template holding all the options and the Instance only referencing to the Template as the only option..
### BGP Templates
This section allows you to set BGP Templates, which are commonly used BGP configuration*themes* to reduce the number of repeated settings while adding BGP Instances.
### BGP Instances
This section allows you to set BGP Instances. The Instances are the ones starting the BGP Protocol and can, or not, use a BGP Template to re-use the common properties.
> **Caution**: Any duplicated option between an Instance and a Template will resolve by using the Instance option and dismissing the Template one. **Instance** > *Template*.
#### BGP Instance Specific Option
- *List Value* **Templates**: Set the BGP Template that will feed the instance. Any option in the Template will be inherited.
#### Common Options
- *Check Box* **Disabled**: Set this Check Box if you do not want to configure and use this Protocol.
- *Text Area* **Description**: Set a descriptive text to identify this protocol and what it does.
- *Text Box* **Import**: Set if the protocol must import routes and which ones.
- **all**: Accept all the incoming routes.
- **none**: Reject all the incoming routes.
- **filter filterName**: Call an existing filter to define which incoming routes will be accepted or rejected.
- *Text Box* **Export**: Set if the protocol must export routes and which ones.
- **all**: Accept all the outgoing routes.
- **none**: Reject all the outgoing routes.
- **filter filterName**: Call an existing filter to define which outgoing routes will be accepted or rejected.
- *List Value* **Table**: Select the Routing Table to be used.
- *List Value* **IGP Table**: Set the IGP Routing Table (Internal BGP). Bird uses the same Routing Table for both External BGP and Internal BGP by default.
- *Text Area* **Source Address**: Set the local IP Address. By default the Router ID will be used.
- *Text Area* **Local AS**: Set the local BGP Autonomous System ID.
- *Text Area* **Local BGP Address**: Set the local BGP Autonomous System IP Address.
- *Text Area* **Neighbor IP Address**: Set BGP neighbour's IP Address.
- *Text Area* **Neighbor AS**: Set BGP neighbour's Autonomous System ID.
- *Check Box* **Next Hop Self**: Overwrite Next Hop cost attributes with its own source address as next hop. Disabled by default as it is only used in some specific instances.
- *Check Box* **Next Hop Keep**: Forward the same Next Hop information even in situations where the system would use its own source address instead. Disabled by default.
- *Check Box* **Route Reflector Server**: Set if BGP instance must act as a Route Reflector Server and expect neighbours AS to act as clients
- *Text Value* **Route Reflector Cluster ID**: Route Reflector service ID to avoid loops. This options is only allowed in the Server (not clients) and it is Router's ID by default.
- *Text Box* **Routes Import Limit**: Set the maximum number of routes the protocol will import.
- *List Value* **Routes Import Limit Action**: Set the action to apply if the *Routes Import Limit* is exceeded. Options are:
- **block**: Block any route exceeding the limit.
- **disable**: Stop the protocol.
- **warn**: Print Log warnings.
- **restart**: Restart the protocol.
- *Text Box* **Routes Export Limit**: Set the maximum number of routes the protocol will export.
- *List Value* **Routes Export Limit Action**: Set the action to apply if the *Routes Export Limit* is exceeded. Options are:
- **block**: Block any route exceeding the limit.
- **disable**: Stop BGP protocol.
- **warn**: Print Log warnings.
- **restart**: Restart BGP protocol.
- *Text Box* **Routes Received Limit**: Set the maximum number of shared routes the Protocol must accept and remember (the **number** of imported routes is not affected by this option).
- *List Value* **Routes Received Limit Action**: Set the action to apply if the *Routes Received Limit* is exceeded. Options are:
- **block**: Block any route exceeding the limit.
- **disable**: Stop BGP protocol.
- **warn**: Print Log warnings.
- **restart**: Restart BGP protocol.
## Filters and Functions<a name="fnf"></a>
The Filters and the Functions Page allows you to edit Bird Daemon Filter and Functions files without requiring you to go to command line. Both Pages share the same code base and the only main change is where they are getting the files from. Therefore, and for documentation simplicity sake, both pages will be covered in this section.
> From version 0.3 onwards:
> The default and supported place to store filter files is under `/etc/bird{4|6}/filters`.
> The default and supported place to store function files is under `/etc/bird{4|6}/functions`.
> Current version 0.3 does not allow changing file names. You will have to change the default filenames through SSH. This will be enhanced in future versions.
#### Components
- *List Value* **Filter Files** / **Function Files**: Set the Filter or Function file to edit from the ones under `/etc/bird{4|6}/filters` / `/etc/bird{4|6}/functions`.
> If you want to create a new Filter or Function file, use the **New File** element in the list.
> The default behaviour is to allow administrators to create new files using this scheme:
> */etc/bird{4|6}/filters/filter*-**TIMESTAMP**. *Timestamp* is: YYYYMMDD-HHMM. I.e. */etc/bird4/filters/filter-20170705-2030*
> */etc/bird{4|6}/functions/function*-**TIMESTAMP**. *Timestamp* is: YYYYMMDD-HHMM. I.e. */etc/bird4/functions/function-20170705-2030*
- *Button* **Load File**: Click this button to Load the file selected in the *{filter|function} Files* list. This button **must** be pressed in order to edit the target file.
- *Read Only Text Box* **Editing File**: This Read-Only field is empty by default. It will get populated with the target file to edit.
> **Caution**: Only if this field shows a file path, the contents of the target file can be edited and saved.
- *Text Area* **File Contents**: This text area will show the contents of the file shown in the *Editting File*. Save the contents of this text area by pressing the Button **Submit**
> Use **spaces** instead of **tabs** for indentation.
> **Caveat**: If you save your filter or function using the *New File* option, until you refresh the page, the **saved** file will still appear as *New File*. However, the file will be created and correctly stored and you will be able to edit it with no problems.
> After refreshing the page, your file will appear normally together with a new *New File* option.
> This behaviour will be enhanced in future versions.
#### Common Errors
Most common errors produced by Filters and Functions are:
- Syntax errors: `bird: /etc/bird4/filters/filter-20170507-0951, line 4: syntax error`
> This instances require you to check where your errors is following Bird's hints.
- Non-existing filter: `bird: /tmp/bird4.conf, line 71: No such filter.`
> Check your Filter name or define it in the **Filters Page**
- Calls to functions not defined in the Functions files or not part of the Bird filter/function definition *language*: `, line 4: You can't call something which is not a function. Really.`
> Check you Function definition, your call name or Bird's official documentation to get the right reference.
#### Critical Errors
There are some critical errors that could escape from first sight as Bird Daemon will start working *correctly*.
If you set your Filter **without** *accept* or *reject* calls, your filter will fail to work and let all the routes pass by as accepted. This will be shown in the **Log Page**:
Example: **Filter "doNothing"**
```
filter doNothing
{
print "HelloWorld";
}
```
This *wrong* filter has been used in our BGP instance and Bird Daemon runs correctly. However, if we check the **Log Page** we find:
```
2017-05-07 10:18:49 <ERR> Filter doNothing did not return accept nor reject. Make up your mind
2017-05-07 10:18:49 <INFO> HelloWorld
```
> Do not leave any filter without *accept* or *reject* calls to avoid this wrong behaviour that will incurr in a waste of resources.

80
bird-openwrt/README.md Normal file
View File

@ -0,0 +1,80 @@
# bird-openwrt
Package for OpenWRT to bring integration with UCI and LUCI to Bird4 and Bird6 daemon.
This repository contains an UCI module adding support for an user-friendly configuration of the BIRD daemon in OpenWRT systems and a LuCI application to control this UCI configuration using the web-based OpenWRT configuration system.
**Package Names**: luci-app-bird{4|6} and bird{4|6}-uci
**Dependences**: +bird{4|6} +libuci +luci-base +uci +libuci-lua
**Last Version**: 0.3
**Terminal (UCI) Documentation**: [Link](https://github.com/eloicaso/bird-openwrt/blob/master/UCI-DOCUMENTATION.md)
**Web (LUCI) Documentation**: [Link](https://github.com/eloicaso/bird-openwrt/blob/master/LUCI-DOCUMENTATION.md)
## Known issues (v0.3):
* There is an issue with pre-built images. It seems that the UCI-Default Scripts are not applied for some reason. If you face this situation, just copy both packages in your /tmp and and execute "opkg install PackageName.ipk --force-reinstall". It will overwrite your /etc/config/bird{4|6}, create a backup of this configuration.
* LUCI Material Design Theme shows a "Loading page" in **Logs Page** preventing it to load. Moreover, the OpenWRT Theme crashes loading the **Log Page**.
Please, go to `System -> Language and Style -> Design` and change it to any other avaiable Theme (*Bootstrap* or *Freifunk_Generic* are recommended).
* There is a manual procedure to designate custom Routing Table IDs created through this package's UI. Please, visit [this page](https://github.com/eloicaso/bgp-bmx6-bird-docn/blob/master/EN/manual_procedures.md) for more details.
## How to compile:
Due to the existence of Routing's bird-openwrt packages, if you want to build your system using this repo's bird packages, you need to proceed as follows:
* Add this github as a repository in feeds.conf. Alternatively, you could use a local git clone)
```
src-git birdwrt https://github.com/eloicaso/bird-openwrt.git
```
OR
```
src-link birdwrt /path/to/your/git/clone/bird-openwrt
```
* Disable OpenWRT-Routing repository to avoid getting the outdated package
```
# src-git routing https://github.com/openwrt-routing/packages.git
```
* Update and install all packages in feeds
```
./scripts/feeds update -a; ./scripts/feeds install -a
```
* Enable OpenWRT-Routing repository to fulfill bird{4/6} dependencies
```
src-git routing https://github.com/openwrt-routing/packages.git
./scripts/feeds update routing; ./scripts/feeds install bird4 bird6
```
* Compile (Option 1) the whole OpenWRT image with the package included
```
make menuconfig -> Network -> Routing and Redirection -> Select bird*-uci
-> LuCI -> 3. Applications -> Select luci-app-bird*
make V=99
```
* Compile (Option 2) the packet ( ! this method requires to compile its dependeces before using Option 1)
```
make package/feeds/birdwrt/bird{4/6}-openwrt/compile V=99
```
* Find your package in
```
[OpenWRT_folder]/bin/packages/{Architecture}/routing/bird{4/6}-uci_{Version}_{Architecture}.ipk
[OpenWRT_folder]/bin/packages/{Architecture}/routing/luci-app-bird{4/6}_{Version}_{Architecture}.ipk
```
* Install your .ipk in your dev-environment (avoid CheckSum Missmatch issues)
```
scp bird{4/6}-uci_{Version}_{Architecture}.ipk user@IPAddres:/tmp
On your Dev-Environment:
opkg install bird{4/6}-uci_{Version}_{Architecture}.ipk --force-checksum
```

View File

@ -0,0 +1,345 @@
<!--
---------------------------------------------------------------------
(C) 2014 - 2017 Eloi Carbo <eloicaso@openmailbox.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
---------------------------------------------------------------------
-->
# Bird{4|6} UCI Packages Documentation
* BIRD Daemon's original documentation: http://bird.network.cz/?get_doc
* Usage examples (Gitlab): https://gitlab.labs.nic.cz/labs/bird/wikis/home
* Extra documentation in English & Catalan: https://github.com/eloicaso/bgp-bmx6-bird-docn
* If you want to add new options to bird*-openwrt packages add a pull request or issue in: https://github.com/eloicaso/bird-openwrt
### Options used in /etc/config/bird{4|6}
> *Clarification*: Any reference to **{4|6}** in this document means that it applies to both Bird4 and Bird6 packages and configurations. Otherwise, the text will clarify which specific package is affected by it.
#### CONFIGURATION SECTION 1: 'bird'
Usage example :
``` Bash
config bird 'bird'
option use_UCI_config '1'
option UCI_config_file '/tmp/bird4.conf'
```
* **use_UCI_config**: *Boolean*
This option allows you to use package's UCI configuration translation instead of using the original Bird config file (hand-edited). If true/1, birdX init.d script will use the translation placed in "UCI_config_file". Otherwise, it will use the default "/etc/birdX.conf" configuration.
**\[HINT**\] This could be used to allow multiple configurations and swap them easily.
*Default: 0*
* **UCI_config_file**: *String* File_path
This option sets where will be placed the translation of the UCI configuration file.
*Default: /tmp/birdX.conf*
#### CONFIGURATION SECTION 2: 'global NAME'
Usage example:
```Bash
config global 'global'
option log_file '/tmp/bird4.log'
option log 'all'
option debug 'off'
option router_id '172.16.1.6'
```
* **log_file**: *String* File_path
This option sets the path of the file used to save Bird Log and Debug's information.
*Default: /tmp/bird{4|6}.log*
* **log**: *String/Enumeration* (all/off, info, warning, error, fatal, debug, trace, remote, auth, bug)
This option allows you to set which information you want to save in the Log file.
**\[HINT\]** Use the enumeration like: { info, waning, error }. Do not enter any extra option if you select "all" (Bird will fail to start).
*Default: all*
* **debug**: *String/Enumeration* ( all/off, states, routes, filters, interfaces, events, packets)
This option allows you to set which **extra** debug information will be saved in the "log_file" file.
**\[HINT\]** Use the enumeration like: { info, waning, error }. Do not enter any extra option if you select "all" (Bird will fail to start).
*Default: off*
* **router_id**: IP Address
This option sets which will be the Router ID.
**\[HINT\]** In **Bird4** this field is the lowest IP address (not loopback) among the existing interfaces by default (Optional property).
In **Bird6** there is no default value and it is mandatory.
* **listen_bgp_addr**: IP Address
This option sets the IP address that Bird BGP instances will listen by default.
*Default: 0.0.0.0*
* **listen_bgp_port**: *Integer* Port
This option sets the port that Bird BGP instances will listen by default.
*Default: IP 0.0.0.0 and Port 179*
* **listen_bgp_dual**: *Boolean*
**\[Bird6\]** This option configures Bird6 BGP instances to listen only IPv6 or IPv4/6 BGP routes.
#### <a name="table"></a>CONFIGURATION SECTION 3: 'table'
Usage example:
``` Bash
config table
option name 'aux'
```
* **name**: *String*
This option allows you to set the name of the auxiliar kernel tables used for Bird. This option is mandatory for most of the protocols.
#### CONFIGURATION SECTION 4: 'kernel NAME'
Usage example:
``` Bash
config kernel kernel1
option table 'aux'
option import 'all'
option export 'all'
option kernel_table '100'
option scan_time '10'
option learn '1'
option persist '0'
option disabled '0'
```
* **table**: *String*
Set an auxiliary table for the current kernel routing instance. This table **MUST** exist as a [table](#table) instance.
**\[HINT\]** If there is an Kernel protocol instance that uses the "main" kernel table, not using table/kernel_table options, this should be included before the rest of Kernel instances (which will use auxiliary tables).
* **import**: *String/Filter* function
This option delimits which routes coming from other protocols will be accepted.
Options are:
**All/none**: allows to import all the routes or none of them.
**Filter name**: \[import 'bgp_filter_in'\] the protocol will use the filter with the given name (Specified filter **must** exists in any file under /etc/bird{4|6}/filters/ folder).
* export: String/Filter function
This option delimits which routes going out from the protocol. This option allows filters in different manners:
**All/none**: allows to export all the routes or none of them.
**Filter name**: \[export 'bgp_filter_out'\] the protocol will use the filter with the given name(Specified filter **must** exists in any file under /etc/bird{4|6}/filters/ folder).
* **kernel_table**: *Integer*
This option sets the identification number of the Kernel table that will be used instead of the main one.
*Default: main table (254)*
* **scan_time**: *Integer*
This option sets the time between checks to target kernel table.
* **learn**: *Boolean*
Set if kernel table will add the routes from other routing protocols or the system administrator.
* **persist**: *Boolean*
Set if Bird Daemon will save the known routes when exiting or if it will clean the routing table.
* **disable**: *Boolean*
This option sets if the protocol will be used or dismissed.
*Default: 0*
#### CONFIGURATION SECTION 5: 'device NAME'
Usage example:
``` Bash
config device device1
option scan_time '10'
option disabled '0'
```
* **scan_time***: *Integer*
This option sets the time between checks to the selected kernel table.
* **disable**: *Boolean*
This option sets if the protocol will be used or dismissed.
*Default: 0*
#### CONFIGURATION SECTION 6: 'static NAME'
Usage example:
``` Bash
config static static1
option table 'aux'
option disabled '0'
```
* **table**: *String*
Set an auxiliary table for the current static instance. This table **MUST** exist as a [table](#table) instance.
**\[HINT\]** If there is an static instance that uses the "main" kernel table (not using table/kernel_table options), this should be included before the rest of static instances (which will use auxiliary tables).
* **disable**: *Boolean*
This option sets if the protocol will be used or dismissed.
*Default: 0*
#### CONFIGURATION SECTION 7 & 8: 'bgp NAME' & 'bgp_template NAME'
This section merges two different configuration sections: BGP *instances* and *templates*. The first one is the basic BGP configuration part and the second one is the template used to minimize the number of options written in the configuration file for each unique instance. Both configuration sections have the same options but, when Bird finds duplicities, the instance will overwrite the template options.
Usage examples:
``` Bash
# instance
config bgp bgp1
option template 'bgp_common'
option description 'Description of the BGP instance'
option neighbor_address '172.16.1.5'
option neighbor_as '65530'
option source_address '172.16.1.6'
option next_hop_self '0'
option next_hop_keep '0'
option rr_client '1'
option rr_cluster_id '172.16.1.6'
```
``` Bash
# template
config bgp_template bgp_common
option table 'aux'
option import 'all'
option export 'all'
option local_address '172.16.1.6'
option local_as '65001'
option import_limit '100'
option import_limit_action 'warn'
option export_limit '100'
option export_limit_action 'warn'
option receive_limit '100'
option receive_limit_action 'warn'
option disabled '0'
```
* **template**: *String*
This option states the template used for current BGP instance. This template MUST exist.
* **description**: *String*
This option allows to add a description of the bgp instance and its function.
* **local_addr**: IP address
This option allows to set the IP source of our Autonomous System (AS).
* **local_as**: *Integer*
This option allows to set the identification number of our AS number. This option is mandatory for each BGP instance.
* **neighbor_addr**: IP address
Each BGP instance has a neighbor connected to. This option allows to set its IP address.
* **neighbor_as**: *Integer*
Each BGP instance has a neighbor connected to. This option allows to set its AS ID.
* **next_hop_self**: *Boolean*
If this option is true, BGP protocol will avoid to calculate the next hop and always advertise own "Router id" IP.
*Default: 0*
* **next_hop_keep**: *Boolean*
If this option is true, BGP will always use the received next_hop information to redirect the route.
*Default: 0*
* **rr_client**: *Boolean*
IF this option is true, the router will be set as Route Reflector and will treat the rest of the routers as RR clients.
*Default: 0*
* **rr_cluster_id**: *Integer*
This option sets the identification number of the RR cluster. All the nodes in a cluster needs this option and share the same number.
*Default: Router id*
* **import_limit**: *Integer*
This option sets the limit of routes that a protocol can import until take the action indicated in the import_limit_action.
import_limit also counts filtered routes (even dropped ones).
*Default: 0 (no limit)*
* **import_limit_action**: *String*
This option allows to decide the action to take when reached the limit of imported routes.
Actions are: warn, block, restart, disable
* **export_limit**: *Integer*
This option sets the limit of routes that a protocol can export until take the action indicated in the export_limit_action.
*Default: 0 (no limit)*
* **export_limit_action**: *String*
This option allows to decide the action to take when reached the limit of exported routes.
Actions are: warn, block, restart, disable
* **receive_limit**: *Integer*
This option sets the limit of routes that a protocol can receive until take the action indicated in the receive_limit_action. receive_limit only counts accepted routes from the protocol.
*Default: 0 (no limit)*
* **receive_limit_action**: *String*
This option allows to decide the action to take when reached the limit of received routes.
Actions are: warn, block, restart, disable
* **disable**: *Boolean*
This option sets if the protocol will be used or dismissed.
*Default: 0*
#### CONFIGURATION SECTION 9: 'route'
Usage example:
``` Bash
config route
option instance 'static1'
option type 'router'
option prefix '192.168.9.0/24'
option via '10.99.105.159'
config route
option instance 'static1'
option type 'special'
option prefix '192.168.2.0/24'
option attribute 'unreachable'
config route
option instance 'static1'
option type 'iface'
option prefix '192.168.3.0/24'
option iface 'mgmt0'
config route
option instance 'static1'
option type 'recursive'
option prefix '192.168.4.0/24'
option ip '192.168.1.1'
config route
option instance 'static1'
option type 'multipath'
option prefix '192.168.30.0/24'
list l_via '172.16.1.5'
list l_via '172.16.1.6'
```
* **instance**: *String*
This option indicates the route that the static protocol instance will apply.
* **type**: *String*
This option states the type of route that will be applied. Also defines the options available for it.
Types are: 'router', 'special', 'iface', 'recursive' or 'multipath'.
* **prefix**: IP address/network
This option allows to define the network that you want to define.
**\[router only\]**
**via**: IP Address
This option indicates the IP address of the neighbor router where the routes will pass through.
**\[special only\]**
**attribute**: *String*
This option will mark the behaviour of the route.
Attribures are: 'blackhole', 'unreachable' or 'prohibit'.
**\[iface only\]**
**iface**: *String*
This option indicates the interface used to redirect the BGP routes. Careful, the interface MUST exist, or Bird will fail to start.
**\[recursive only\]**
**ip**: IP address
This option states the IP address which the next hop will depend on.
**\[multipath only\]**
This is a list, not an option. Use it as in the example, or check the UCI configuration documentation.
**l_via**: IP address
This list of IPs specifies the list (following the sequence) of routers that the route will follow as next hops.
#### CONFIGURATION SECTION 10 & 11: 'filter NAME' & 'function Name'
Filters are written in separated files under **/etc/bird{4|6}/filters/** and **/etc/bird{4|6}/functions/**. Their syntax can be found [here.](http://bird.network.cz/?get_doc&f=bird-5.html)
The content of each filter and file file will be included in the resulting bird{4|6}.conf file without checking its syntax, so you could find errors during start time.
* Clarification for any existing **v0.2** user: an automated upgrade path has been added to switch your old "filter" or "function" sections. It is safe to upgrade, but doing regular backups of your key files is always a good practise to avoid frustration.

View File

@ -1,5 +1,4 @@
# Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
# BGP/Bird integration with OpenWRT and QMP
# Copyright (C) 2014-2017 Eloi Carbo <eloicaso@openmailbox.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -18,14 +17,14 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
BIRD:=bird4
PKG_NAME:=$(BIRD)-openwrt
PKG_RELEASE:=0.2
BIRD := bird4
PKG_NAME := $(BIRD)-openwrt
PKG_VERSION := 0.3
PKG_RELEASE := 1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_LICENSE:=GPL-3.0+
uci:=$(BIRD)-uci
luci:=luci-app-$(BIRD)
PKG_LICENSE := GPL-3.0+
uci := $(BIRD)-uci
luci := luci-app-$(BIRD)
include $(INCLUDE_DIR)/package.mk
@ -40,7 +39,7 @@ define Package/$(uci)
CATEGORY:=Network
SUBMENU:=Routing and Redirection
MAINTAINER:=Eloi Carbo <eloicaso@openmailbox.org>
URL:=https://github.com/eloicaso/bird4-openwrt/
URL:=https://github.com/eloicaso/bird-openwrt/
DEPENDS:=+$(BIRD) +libuci +uci
endef
@ -48,32 +47,42 @@ define Package/$(uci)/description
$(BIRD) UCI integration module
endef
define Package/$(uci)/conffiles
/etc/config/$(BIRD)
endef
define Package/$(uci)/install
$(INSTALL_DIR) $(1)/etc/$(BIRD)/init.d
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_BIN) ./src/init.d/$(BIRD) $(1)/etc/$(BIRD)/init.d/
$(CP) ./src/uci-defaults/$(uci)-install-init.d $(1)/etc/$(BIRD)/init.d/
$(CP) ./src/config/$(BIRD) $(1)/etc/config/
$(INSTALL_DIR) $(1)/etc/$(BIRD)/filters
$(INSTALL_DIR) $(1)/etc/$(BIRD)/functions
$(INSTALL_BIN) ./src/init.d/$(BIRD)* $(1)/etc/$(BIRD)/init.d/
$(CP) ./src/uci-defaults/* $(1)/etc/$(BIRD)/init.d/
$(INSTALL_CONF) ./src/config/$(BIRD) $(1)/etc/config/
endef
define Package/$(uci)/postinst
#!/bin/sh
if [ -z $${IPKG_INSTROOT} ]; then
( . /etc/bird4/init.d/bird4-uci-install-init.d ) && rm -f /etc/bird4/init.d/bird4-uci-install-init.d
fi
if [ -z "$${IPKG_INSTROOT}" ]; then
( . /etc/$(BIRD)/init.d/bird-uci-install-init.d $(BIRD) ) && rm -f /etc/$(BIRD)/init.d/bird-uci-install-init.d
( . /etc/$(BIRD)/init.d/99-relocate-filters $(BIRD) ) && rm -f /etc/$(BIRD)/init.d/99-relocate-filters
if [ -f /etc/sysupgrade.conf ] && ! grep $(BIRD) /etc/sysupgrade.conf; then
echo /etc/config/$(BIRD) >> /etc/sysupgrade.conf
echo /etc/$(BIRD)/filters/ >> /etc/sysupgrade.conf
echo /etc/$(BIRD)/functions/ >> /etc/sysupgrade.conf
fi
fi
endef
$(eval $(call BuildPackage,$(uci)))
define Package/$(luci)
TITLE:=LuCI support for $(BIRD)
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
MAINTAINER:=Eloi Carbo <eloicaso@openmailbox.org>
URL:=https://github.com/eloicaso/bird4-openwrt/
URL:=https://github.com/eloicaso/bird-openwrt/
DEPENDS:=+$(BIRD)-uci +luci-base
endef
@ -84,8 +93,10 @@ endef
define Package/$(luci)/install
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/$(BIRD)/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/$(BIRD)/
$(CP) ./src/model/* $(1)/usr/lib/lua/luci/model/cbi/$(BIRD)/
$(CP) ./src/controller/* $(1)/usr/lib/lua/luci/controller/
$(CP) ./src/view/* $(1)/usr/lib/lua/luci/view/$(BIRD)/
endef
$(eval $(call BuildPackage,$(luci)))

View File

@ -10,11 +10,10 @@ config global 'global'
option log_file '/tmp/bird4.log'
option log 'all'
option debug 'off'
option router_id '172.16.1.6'
config table
option name 'aux'
config kernel kernel1
option table 'aux'
option import 'all'
@ -32,36 +31,3 @@ config device device1
config static static1
option table 'aux'
option disabled '0'
config bgp bgp1
option template 'bgp_common'
option description 'Description of the BGP instance'
option neighbor_address '172.16.1.5'
option neighbor_as '65530'
option source_address '172.16.1.6'
option next_hop_self '0'
option next_hop_keep '0'
option rr_client '1'
option rr_cluster_id '172.16.1.6'
config bgp_template bgp_common
option table 'aux'
option import 'all'
option export 'all'
option local_address '172.16.1.6'
option local_as '65001'
option import_limit '100'
option import_limit_action 'warn'
option export_limit '100'
option export_limit_action 'warn'
option receive_limit '100'
option receive_limit_action 'warn'
option disabled '0'
config route
option instance 'static1'
option type 'router'
option prefix '192.168.9.0/24'
option via '10.99.105.159'

View File

@ -1,6 +1,5 @@
--[[
Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
BGP/Bird integration with OpenWRT and QMP
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -19,9 +18,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
module("luci.controller.bird4", package.seeall)
function index()
entry({"admin","network","bird4"}, cbi("bird4/overview"), "Bird4", 0).dependent=false
entry({"admin","network","bird4","overview"}, cbi("bird4/overview"), "Overview", 1).dependent=false
entry({"admin","network","bird4","proto_general"}, cbi("bird4/gen_proto"), "General protocols", 3).dependent=false
entry({"admin","network","bird4","proto_bgp"}, cbi("bird4/bgp_proto"), "BGP Protocol", 4).dependent=false
end
entry({"admin", "network", "bird4",},
alias("admin", "network", "bird4", "status"),
_("Bird4"), 0)
entry({"admin", "network", "bird4", "status"},
cbi("bird4/status"),
_("Status"), 0).leaf = true
entry({"admin","network","bird4","log"},
template("bird4/log"),
_("Log"), 1).leaf = true
entry({"admin", "network", "bird4", "overview"},
cbi("bird4/overview"),
_("Overview"), 2).leaf = true
entry({"admin","network","bird4","proto_general"},
cbi("bird4/gen_proto"),
_("General protocols"), 3).leaf = true
entry({"admin","network","bird4","proto_bgp"},
cbi("bird4/bgp_proto"),
_("BGP Protocol"), 4).leaf = true
entry({"admin","network","bird4","filters"},
cbi("bird4/filters"),
_("Filters"), 5).leaf = true
entry({"admin","network","bird4","functions"},
cbi("bird4/functions"),
_("Functions"), 6).leaf = true
end

View File

@ -1,7 +1,6 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
# BGP/Bird integration with OpenWRT and QMP
# Copyright (C) 2014-2017 - Eloi Carbo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -17,395 +16,218 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Extra Service Function to get the Status of the Service
# This complements /etc/rc.common functions
# Commands ending with *_quiet are meant to be ran in Luci. These
# scripts' return minimal output.
EXTRA_COMMANDS="status start_quiet stop_quiet restart_quiet status_quiet"
EXTRA_HELP=" status Returns service status"
BIRD="bird4"
BIRD_CONFIG="/etc/$BIRD.conf"
BIRD_CONFIG="/etc/${BIRD}.conf"
BIRD_LOG="/var/log/${BIRD}.log"
BIRD_ERR="/tmp/${BIRD}.err"
START=99
STOP=10
SERVICE_DAEMONIZE=1
SERVICE_USE_PID=1
SERVICE_PID_FILE="/var/run/$BIRD.pid"
SERVICE_PID_FILE="/var/run/${BIRD}.pid"
BIRD_BIN="/usr/sbin/$BIRD"
BIRD_BIN="/usr/sbin/${BIRD}"
# Special non-terminal-rich output for Luci calls
LUCI="false"
# Function: writeToConfig $1
# $1 string.
# Allows to write in the $BIRD_CONFIG file, the string $1. This function does not check the $1 string.
# Example: writeToConfig "value: $N"
writeToConfig() {
echo "$1" >> $BIRD_CONFIG
}
# Function: write $1 $2
# $1 string. $2 string.
# This function checks if $2 is empty. If not, it writes the string $1 in the $BIRD_CONFIG file.
# Use write function to check if $1, value found inside $2, is not empty and can be written in the configuration file.
# Example: N=""; write "value: $N" $N;
write() {
[ -n "$2" ] && writeToConfig "$1"
}
#Function: write_bool $1 $2
# $1 string; $2 boolean
# This function checks if $2 is true or false and write the $1 string into $BIRD_CONFIG file.
# The function writes a # before the $2 string if its false.
# Example: local N=0; write_bool $N
write_bool() {
[ "$2" == 0 ] && writeToConfig "# $1;" || writeToConfig " $1;"
}
# Function: get $1 $2
# $1 string. $2 string
# This function uses the external UCI function "config_get $result $section $option" to obtain a string value from UCI config file.
# To use this function, use the same name of the UCI option for the variable.
# Example: UCI (option id 'abcd'); local id; get id $section
get() {
config_get $1 $2 $1
}
# Function: get_bool $1 $2
# $1 boolean. $2 string
# This function uses the external UCI function "config_get_bool $result $section $option" to obtain a boolean value from UCI config file.
# To use this function, use the same name of the UCI option for the variable $1.
# Example: UCI (option use_ipv6 '1'); local use_ipv6; get use_ipv6 $section
get_bool() {
config_get_bool $1 $2 $1
}
# Function: multipath_list $1
# $1 string
# This function writes the $1 string in the multipath routes.
multipath_list() {
write " via $1" $1
}
# Function: prepare_tables $1
# $1 string
# This function gets each "table" section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI table section
prepare_tables() {
local section="$1"; local name
get name $section
write "table $name;" $name
}
# Function: prepare_global $1
# $1 string
# This function gets each "global" section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI global section. prepare_global is the first configuration set in the bird4.conf and removes the old file.
prepare_global () {
local section="$1"
local log_file; local log; local debug; local router_id; local table
# Remove old configuration file
rm -f "$BIRD_CONFIG"
get log_file $section
get log $section
get debug $section
get router_id $section
get table $section
# First line of the NEW configuration file
echo "#Bird4 configuration using UCI:" > $BIRD_CONFIG
writeToConfig " "
[ -n "$log_file" -a -n "$log" ] && writeToConfig 'log "'$log_file'" '$log';'
write "debug protocols $debug;" $debug
writeToConfig " "
writeToConfig "#Router ID"
write "router id $router_id;" $router_id
writeToConfig " "
writeToConfig "#Secondary tables"
config_foreach prepare_tables 'table'
writeToConfig " "
}
# Function: prepare_routes $1
# $1 string
# This function gets each "route" section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI route section. Each type of route has its own treatment.
prepare_routes() {
local instance; local prefix; local via; local type
local section="$1"
local protoInstance="$2"
get instance $section
if [ "$instance" = "$protoInstance" ]; then
get type $section
case "$type" in
"router")
get prefix $section
get via $section
[ -n "$prefix" -a -n "$via" ] && writeToConfig " route $prefix via $via;"
;;
"special")
get prefix $section
get attribute $section
[ -n "$prefix" -a -n "$attribute" ] && writeToConfig " route $prefix $attribute;"
;;
"iface")
get prefix $section
get iface $section
[ -n "$prefix" -a -n "$iface" ] && writeToConfig ' route '$prefix' via "'$iface'";'
;;
"multipath")
get prefix $section
write " route $prefix multipath" $prefix
config_list_foreach $section l_via multipath_list
writeToConfig " ;"
;;
esac
fi
}
# Function: prepare_kernel $1
# $1 string
# This function gets each "kernel" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI kernel section.
prepare_kernel() {
local section="$1"
write "#$section configuration:" $section
local disabled; local table; local kernel_table; local import; local export; local scan_time; local persist; local learn
get_bool disabled $section
get table $section
get import $section
get export $section
get scan_time $section
get kernel_table $section
get learn $section
get persist $section
writeToConfig "protocol kernel {"
write_bool disabled $disabled
write " table $table;" $table
write " kernel table $kernel_table;" $kernel_table
write_bool learn $learn
write_bool persist $persist
write " scan time $scan_time;" $scan_time
write " import $import;" $import
write " export $export;" $export
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_static $1
# $1 string
# This function gets each "static" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI static section.
prepare_static() {
local section="$1"
local disabled
get disabled $section
if [ "$disabled" -eq 0 ]; then
local table
get table $section
writeToConfig "#$section configration:" $section
writeToConfig "protocol static {"
write " table $table;" $table
config_foreach prepare_routes 'route' $section
writeToConfig "}"
writeToConfig " "
fi
}
# Function: prepare_device $1
# $1 string
# This function gets each "device" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI device section.
prepare_device() {
local section="$1"
local disabled; local scan_time
get disabled $section
get scan_time $section
write "#$section configuration:" $section
writeToConfig "protocol device {"
write_bool disabled $disabled
write " scan time $scan_time;" $scan_time
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp_template $1
# $1 string
# This function gets each "bgp_template" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI bgp_template section.
# Careful! Template options will be replaced by "instance" options if there is any match.
prepare_bgp_template() {
local section="$1"
local disabled; local table; local import; local export; local local_address; local local_as; local neighbor_address; local neighbor_as; local source_address; local next_hop_self; local next_hop_keep; local rr_client; local rr_cluster_id; local import_limit; local import_limit_action; local export_limit; local export_limit_action; local receive_limit; local receive_limit_action
get_bool disabled $section
get_bool next_hop_self $section
get_bool next_hop_keep $section
get table $section
get import $section
get export $section
get local_address $section
get local_as $section
get rr_client $section
get rr_cluster_id $section
get import_limit $section
get import_limit_action $section
get export_limit $section
get export_limit_action $section
get receive_limit $section
get receive_limit_action $section
get neighbor_address $section
get neighbor_as $section
writeToConfig "#$section template:"
writeToConfig "template bgp $section {"
[ -n "$disabled" ] && write_bool disabled $disabled
write " table $table;" $table
write " local as $local_as;" $local_as
write " source address $local_address;" $local_address
write " import $import;" $import
write " export $export;" $export
if [ -n "$next_hop_self" ]; then
[ "$next_hop_self" = "1" ] && writeToConfig " next hop self;" || writeToConfig "# next hop self;"
fi
if [ -n "$next_hop_keep" ]; then
[ "$next_hop_keep" = "1" ] && writeToConfig " next hop keep;" || writeToConfig "# next hop keep;"
fi
[ "$rr_client" = "1" ] && writeToConfig " rr client;" || writeToConfig "# rr client;"
write " rr cluster id $rr_cluster_id;" $rr_cluster_id
if [ -n "$import_limit" -a "$import_limit" > "0" ]; then
[ -z "$import_limit_action" ] && $import_limit_action = "warn"
writeToConfig " import limit $import_limit action $import_limit_action;"
fi
if [ -n "$export_limit" -a "$export_limit" > "0" ]; then
[ -z "$export_limit_action" ] && $export_limit_action = "warn"
writeToConfig " export limit $export_limit action $export_limit_action;"
fi
if [ -n "$receive_limit" -a "$receive_limit" > "0" ]; then
[ -z "$receive_limit_action" ] && $receive_limit_action = "warn"
writeToConfig " receive limit $receive_limit action $receive_limit_action;"
fi
[ -n "$neighbor_address" -a -n "$neighbor_as" ] && writeToConfig " neighbor $neighbor_address as $neighbor_as;"
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp $1
# $1 string
# This function gets each "bgp" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI bgp section.
# Careful! The options set in bgp instances overlap bgp_template ones.
prepare_bgp() {
local section="$1"
local disabled; local table; local template; local description; local import; local export; local local_address; local local_as; local neighbor_address; local neighbor_as; local rr_client; local rr_cluster_id; local import_limit; local import_limit_action; local export_limit; local export_limit_action; local receive_limit; local receive_limit_action
get disabled $section
get table $section
get template $section
get description $section
get import $section
get export $section
get local_address $section
get local_as $section
get rr_client $section
get rr_cluster_id $section
get import_limit $section
get import_limit_action $section
get export_limit $section
get export_limit_action $section
get receive_limit $section
get receive_limit_action $section
get neighbor_address $section
get neighbor_as $section
writeToConfig "#$section configuration:"
[ -n "$template" ] && writeToConfig "protocol bgp $section from $template {" || writeToConfig "protocol bgp $section {"
[ -n "$disabled" ] && write_bool disabled $disabled
write " table $table;" $table
# [ -n "$description" ] && writeToConfig ' description "'$description'";'
write " local as $local_as;" $local_as
write " source address $local_address;" $local_address
write " import $import;" $import
write " export $export;" $export
if [ -n "$next_hop_self" ]; then
[ "$next_hop_self" = "1" ] && writeToConfig " next hop self;" || writeToConfig "# next hop self;"
fi
if [ -n "$next_hop_keep" ]; then
[ "$next_hop_keep" = "1" ] && writeToConfig " next hop keep;" || writeToConfig "# next hop keep;"
fi
[ "$rr_client" = "1" ] && writeToConfig " rr client;" || writeToConfig "# rr client;"
write " rr cluster id $rr_cluster_id;" $rr_cluster_id
if [ -n "$import_limit" -a "$import_limit" > "0" ]; then
[ -z "$import_limit_action" ] && $import_limit_action = "warn"
writeToConfig " import limit $import_limit action $import_limit_action;"
fi
if [ -n "$export_limit" -a "$export_limit" > "0" ]; then
[ -z "$export_limit_action" ] && $export_limit_action = "warn"
writeToConfig " export limit $export_limit action $export_limit_action;"
fi
if [ -n "$receive_limit" -a "$receive_limit" > "0" ]; then
[ -z "$receive_limit_action" ] && $receive_limit_action = "warn"
writeToConfig " receive limit $receive_limit action $receive_limit_action;"
fi
[ -n "$neighbor_address" -a -n "$neighbor_as" ] && writeToConfig " neighbor $neighbor_address as $neighbor_as;"
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp_filters $1
# $1 string
# This function gets each "bgp_filter" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI bgp_filter section.
# This function checks if the filter file exists and, in that case, it writes its content to the configuration file.
prepare_bgp_filters() {
local section="$1"
local type
local file_path
get type $section
get file_path $section
if [ -e "$file_path" ]; then
local filter_content=`cat $file_path`
if [ -n "$type" -a "$type" = "bgp" ]; then
writeToConfig "#Filter $section:"
writeToConfig "${filter_content}"
writeToConfig " "
fi
fi
}
. /etc/${BIRD}/init.d/${BIRD}-lib.sh
start() {
config_load bird4
config_load ${BIRD}
local use_UCI_config
get use_UCI_config 'bird'
if [ -z "$use_UCI_config" -o "$use_UCI_config" = "0" ]; then
service_start $BIRD_BIN -d -c $BIRD_CONFIG -P $SERVICE_PID_FILE
#Start the service
if [ "${LUCI}" == "false" ]; then
echo "Starting ${BIRD} Service [ ... ]"
fi
if [ -f ${BIRD_ERR} ]; then
echo -n "" > ${BIRD_ERR}
else
touch ${BIRD_ERR}
fi
if [ -z "${use_UCI_config}" -o "${use_UCI_config}" = "0" ]; then
# Disable Custom bird-openwrt settings.
# Use default behaviour and files
${BIRD_BIN} -d -c ${BIRD_CONFIG} -P ${SERVICE_PID_FILE} -D ${BIRD_LOG} &> ${BIRD_ERR} &
else
#Set Bird4 configuration location:
local UCI_config_File
get UCI_config_File 'bird'
BIRD_CONFIG=${UCI_config_File:-/tmp/bird4.conf}
local UCI_config_file
local log_file
get UCI_config_file 'bird'
get log_file 'global'
BIRD_CONFIG="${UCI_config_file:-$BIRD_CONFIG}"
BIRD_LOG="${log_file:-$BIRD_LOG}"
#Backup previous configuration
[ -f ${BIRD_CONFIG} ] && cp ${BIRD_CONFIG} ${BIRD_CONFIG}.bak
#Setup the basic configuration
prepare_global 'global'
# Gather and set all Functions
gather_functions
# Gather and set all Filters
gather_filters
# Setup Main Protocols
config_foreach prepare_kernel 'kernel'
config_foreach prepare_static 'static'
config_foreach prepare_device 'device'
#config_foreach prepare_direct 'direct'
#Setup the protocols configuration (currently BGP only)
config_foreach prepare_direct 'direct'
config_foreach prepare_pipe 'pipe'
#Setup protocol's configuration: BGP
config_foreach prepare_bgp_template 'bgp_template'
config_foreach prepare_bgp 'bgp'
config_foreach prepare_bgp_filters 'filter'
#Setup protocol's configuration: OSPF
config_foreach prepare_ospf_instance 'ospf'
#Start the service
service_start $BIRD_BIN -d -c $BIRD_CONFIG -P $SERVICE_PID_FILE
${BIRD_BIN} -d -c ${BIRD_CONFIG} -P ${SERVICE_PID_FILE} -D ${BIRD_LOG} &>${BIRD_ERR} &
fi
while [ ! -s ${SERVICE_PID_FILE} ]; do
sleep 1
if [ -s ${BIRD_ERR} ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Start Status: \033[0;31m[ FAILED ]\e[m"
cat ${BIRD_ERR}
cat ${BIRD_ERR} >> ${BIRD_LOG}
else
echo "${BIRD} - Failed: $(cat ${BIRD_ERR})"
cat ${BIRD_ERR} >> ${BIRD_LOG}
fi
break
fi
done
# PID & ERROR contents are read from their files to avoid an issue
# where if [ -s ${SERVICE_PID_FILE} ] and if [ -s ${BIRD_ERR} ]
# fails unless a previous command reads its contents making its
# behaviour unreliable.
SVC_PID="$(cat ${SERVICE_PID_FILE})"
BRDERR_TXT="$(cat ${BIRD_ERR})"
if [ -n "${SVC_PID}" ]; then
if [ -n "${BRDERR_TXT}" ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon already started. Status \033[0;32m[ RUNNING ]\e[m"
else
echo "${BIRD} already started"
fi
else
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Start Status: \033[0;32m[ STARTED ]\e[m"
else
echo "${BIRD} - Started"
fi
fi
# PID File found (service started correctly)
return 0
fi
# PID File not found (error while starting service)
return 1
}
stop() {
service_stop $BIRD_BIN
if [ -s ${SERVICE_PID_FILE} ]; then
config_load ${BIRD}
local log_file
get log_file 'global'
BIRD_LOG="${log_file:-$BIRD_LOG}"
start-stop-daemon -p ${SERVICE_PID_FILE} -K 2>&1 >> ${BIRD_LOG}
if [ $? -eq 0 ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Stop Status: \033[0;32m[ OK ]\e[m"
else
echo "${BIRD} - Stopped"
fi
echo -n "" > ${BIRD_ERR}
else
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Stop Status: \033[0;31m[ FAILED ]\e[m"
echo "Check ${BIRD_LOG} file for more information."
else
echo "${BIRD} Failed to Stop. See Log file: ${BIRD_LOG}"
fi
fi
else
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Service already stopped. \033[0;31m[ FAILED ]\e[m"
else
echo "${BIRD} already stopped"
fi
fi
return 0
}
restart() {
stop
sleep 1
if [ "${LUCI}" == "true" ]; then
echo " ... "
fi
start
}
reload() {
service_reload $BIRD_BIN
service_reload ${BIRD_BIN}
}
status() {
if [ -s ${SERVICE_PID_FILE} ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} start status: \033[0;32m[ RUNNING ]\e[m"
else
echo "${BIRD}: Running"
fi
return 0
else
if [ -s ${BIRD_ERR} ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} service status: \033[0;31m[ STOPPED ]\e[m"
cat ${BIRD_ERR}
else
echo "${BIRD}: Failed - $(cat ${BIRD_ERR})"
fi
return 2
else
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} service status: \033[0;31m[ STOPPED ]\e[m"
else
echo "${BIRD}: Stopped"
fi
return 1
fi
fi
}
# Luci-specific calls (stripped output).
# The following scripts are not meant to be ran using Ash Terminal
# Used in: LUCI/model/cbi/bird4/status.lua
start_quiet() {
LUCI="true"
start
}
stop_quiet() {
LUCI="true"
stop
}
restart_quiet() {
LUCI="true"
restart
}
status_quiet() {
LUCI="true"
status
}

View File

@ -0,0 +1,587 @@
# Bird4-OpenWRT Library - Functions used in /etc/init.d/bird4 script.
#
#
# Copyright (C) 2014-2017 - Eloi Carbo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Function: writeToConfig $1
# $1 string.
# Allows to write in the $BIRD_CONFIG file, the string $1. This function does not check the $1 string.
# Example: writeToConfig "value: $N"
writeToConfig() {
echo "$1" >> ${BIRD_CONFIG}
}
# Function: write $1 $2
# $1 string. $2 string.
# This function checks if $2 is empty. If not, it writes the string $1 in the $BIRD_CONFIG file.
# Use write function to check if $1, value found inside $2, is not empty and can be written in the configuration file.
# Example: N=""; write "value: $N" $N;
write() {
[ -n "$2" ] && writeToConfig "$1"
}
#Function: write_bool $1 $2
# $1 string; $2 boolean
# This function checks if $2 is true and write the $1 string into $BIRD_CONFIG file.
# Example: local N=0; write_bool $N
write_bool() {
[ "$2" == 1 ] && writeToConfig " $1;"
}
# Function: get $1 $2
# $1 string. $2 string
# This function uses the external UCI function "config_get $result $section $option" to obtain a string value from UCI config file.
# To use this function, use the same name of the UCI option for the variable.
# Example: UCI (option id 'abcd'); local id; get id $section
get() {
config_get $1 $2 $1
}
# Function: get_bool $1 $2
# $1 boolean. $2 string
# This function uses the external UCI function "config_get_bool $result $section $option" to obtain a boolean value from UCI config file.
# To use this function, use the same name of the UCI option for the variable $1.
# Example: UCI (option use_ipv6 '1'); local use_ipv6; get use_ipv6 $section
get_bool() {
config_get_bool $1 $2 $1
}
# Function: multipath_list $1
# $1 string
# This function writes the $1 string in the multipath routes.
multipath_list() {
write " via $1" $1
}
# Function: range_list $1
# $1 string
# This function writes the $1 string in the OSPF networks.
range_list(){
write " $1;" $1
}
# Function: hidden_range_list $1
# $1 string
# This function writes the $1 string in the OSPF networks as hidden.
hidden_range_list(){
write " $1 hidden;" $1
}
# Function: prepare_tables $1
# $1 string
# This function gets each "table" section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI table section
prepare_tables() {
local section="$1"; local name
get name ${section}
write "table ${name};" ${name}
}
# Function: prepare_global $1
# $1 string
# This function gets each "global" section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI global section. prepare_global is the first configuration set in the bird4.conf and removes the old file.
prepare_global () {
local section="$1"
local log_file; local log; local debug; local router_id; local table
# Remove old configuration file
rm -f "${BIRD_CONFIG}"
get log_file ${section}
get log ${section}
get debug ${section}
get router_id ${section}
get table ${section}
# First line of the NEW configuration file
echo "#Bird4 configuration using UCI:" > ${BIRD_CONFIG}
writeToConfig " "
#TODO: Set Syslog as receiver if empty
# LOGF="${log_file:-syslog]}"
#TODO: If $log/$debug are empty, set to off
if [ -n "${log_file}" -a -n "${log}" ]; then
firstEntry="${log:0:3}"
if [ "${firstEntry}" = "all" -o "${firstEntry}" = "off" ]; then
writeToConfig 'log "'${log_file}'" '${firstEntry}';'
else
logEntries=$(echo ${log} | tr " " ",")
writeToConfig "log \"${log_file}\" { ${logEntries} };"
fi
fi
if [ -n "${debug}" ]; then
firstEntry="${debug:0:3}"
if [ "${firstEntry}" = "all" -o "${firstEntry}" = "off" ]; then
writeToConfig "debug protocols ${firstEntry};"
else
debugEntries=$(echo ${debug} | tr " " ",")
writeToConfig "debug protocols { ${debugEntries} };"
fi
fi
writeToConfig " "
writeToConfig "#Router ID"
write "router id ${router_id};" ${router_id}
writeToConfig " "
writeToConfig "#Secondary tables"
config_foreach prepare_tables 'table'
writeToConfig " "
}
# Function: prepare_routes $1
# $1 string
# This function gets each "route" section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI route section. Each type of route has its own treatment.
prepare_routes() {
local instance; local prefix; local via; local type; local attribute; local iface
local section="$1"
local protoInstance="$2"
get instance ${section}
get type ${section}
get prefix ${section}
if [ "${instance}" = "${protoInstance}" ]; then
case "${type}" in
"router")
get via ${section}
[ -n "${prefix}" -a -n "${via}" ] && writeToConfig " route ${prefix} via ${via};"
;;
"special")
get attribute ${section}
[ -n "${prefix}" -a -n "${attribute}" ] && writeToConfig " route ${prefix} ${attribute};"
;;
"iface")
get iface ${section}
[ -n "${prefix}" -a -n "${iface}" ] && writeToConfig ' route '${prefix}' via "'${iface}'";'
;;
"multipath")
write " route ${prefix} multipath" ${prefix}
config_list_foreach ${section} l_via multipath_list
writeToConfig " ;"
;;
esac
fi
}
# Function: prepare_kernel $1
# $1 string
# This function gets each "kernel" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI kernel section.
prepare_kernel() {
local section="$1"
local disabled; local table; local kernel_table; local import; local export
local scan_time; local persist; local learn
get_bool disabled ${section}
get table ${section}
get import ${section}
get export ${section}
get scan_time ${section}
get kernel_table ${section}
get learn ${section}
get persist ${section}
write "#${section} configuration:" ${section}
writeToConfig "protocol kernel ${section} {" ${section}
write_bool disabled ${disabled}
write " table ${table};" ${table}
write " kernel table ${kernel_table};" ${kernel_table}
write_bool learn ${learn}
write_bool persist ${persist}
write " scan time ${scan_time};" ${scan_time}
write " import ${import};" ${import}
write " export ${export};" ${export}
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_static $1
# $1 string
# This function gets each "static" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI static section.
prepare_static() {
local section="$1"
local disabled; local table
get disabled ${section}
get table ${section}
if [ "${disabled}" -eq 0 ]; then
writeToConfig "#${section} configration:" ${section}
writeToConfig "protocol static {"
write " table ${table};" ${table}
config_foreach prepare_routes 'route' ${section}
writeToConfig "}"
writeToConfig " "
fi
}
# Function: prepare_direct $1
# $1 string
# This function gets each "direct" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI direct section.
prepare_direct() {
local section="$1"
local disabled; local interface
get disabled ${section}
get interface ${section}
write "#${section} configuration:" ${section}
writeToConfig "protocol direct {"
write_bool disabled ${disabled}
write " interface ${interface};" ${interface}
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_pipe $1
# $1 string
# This function gets each "pipe" protocol section in the UCI configuration an
# $1 is set as the ID of the current UCI direct section.
prepare_pipe() {
local section="$1"
local disabled; local table; local peer_table; local mode; local import; local export
get disabled $section
get peer_table $section
get mode $section
get table $section
get import $section
get export $section
write "#$section configuration:" $section
writeToConfig "protocol pipe $section {" $section
write_bool disabled $disabled
write " table $table;" $table
write " peer table $peer_table;" $peer_table
write " mode $mode;" $mode
write " import $import;" $import
write " export $export;" $export
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_device $1
# $1 string
# This function gets each "device" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI device section.
prepare_device() {
local section="$1"
local disabled; local scan_time
get disabled ${section}
get scan_time ${section}
write "#${section} configuration:" ${section}
writeToConfig "protocol device {"
write_bool disabled ${disabled}
write " scan time ${scan_time};" ${scan_time}
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp_template $1
# $1 string
# This function gets each "bgp_template" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI bgp_template section.
# Careful! Template options will be replaced by "instance" options if there is any match.
prepare_bgp_template() {
local section="$1"
local disabled; local table; local import; local export
local local_as; local neighbor_address; local neighbor_as; local source_address
local next_hop_self; local next_hop_keep; local rr_client; local rr_cluster_id
local import_limit; local import_limit_action; local export_limit; local export_limit_action
local receive_limit; local receive_limit_action; local igp_table
get_bool disabled ${section}
get table ${section}
get import ${section}
get export ${section}
get source_address ${section}
get local_as ${section}
get neighbor_address ${section}
get neighbor_as ${section}
get_bool next_hop_self ${section}
get_bool next_hop_keep ${section}
get rr_client ${section}
get rr_cluster_id ${section}
get import_limit ${section}
get import_limit_action ${section}
get export_limit ${section}
get export_limit_action ${section}
get receive_limit ${section}
get receive_limit_action ${section}
get igp_table ${section}
writeToConfig "#${section} template:"
writeToConfig "template bgp ${section} {"
[ -n "${disabled}" ] && write_bool disabled ${disabled}
[ -n "${table}" ] && writeToConfig " table ${table};"
[ -n "${igp_table}" ] && writeToConfig " igp table ${igp_table};"
[ -n "${local_as}" ] && writeToConfig " local as ${local_as};"
[ -n "${source_address}" ] && writeToConfig " source address ${source_address};"
[ -n "${import}" ] && writeToConfig " import ${import};"
[ -n "${export}" ] && writeToConfig " export ${export};"
[ -n "${neighbor_address}" -a -n "${neighbor_as}" ] && writeToConfig " neighbor ${neighbor_address} as ${neighbor_as};"
if [ -n "${import_limit}" -a "${import_limit}" > "0" ]; then
[ -z "${import_limit_action}" ] && ${import_limit_action} = "warn"
writeToConfig " import limit ${import_limit} action ${import_limit_action};"
fi
if [ -n "${export_limit}" -a "${export_limit}" > "0" ]; then
[ -z "${export_limit_action}" ] && ${export_limit_action} = "warn"
writeToConfig " export limit ${export_limit} action ${export_limit_action};"
fi
if [ -n "${receive_limit}" -a "${receive_limit}" > "0" ]; then
[ -z "${receive_limit_action}" ] && ${receive_limit_action} = "warn"
writeToConfig " receive limit ${receive_limit} action ${receive_limit_action};"
fi
[ -n "${next_hop_self}" ] && write_bool " next hop self;" ${next_hop_self}
[ -n "${next_hop_keep}" ] && write_bool " next hop keep;" ${next_hop_keep}
[ -n "${rr_client}" ] && write_bool " rr client;" ${rr_client}
[ -n "${rr_cluster_id}" ] && writeToConfig " rr cluster id ${rr_cluster_id};"
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp $1
# $1 string
# This function gets each "bgp" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI bgp section.
# Careful! The options set in bgp instances overlap bgp_template ones.
prepare_bgp() {
local section="$1"
local disabled; local table; local template; local description; local igp_table; local passive
local import; local export; local source_address; local local_as; local neighbor_address
local neighbor_as; local rr_client; local rr_cluster_id; local import_limit
local import_limit_action; local export_limit; local export_limit_action
local receive_limit; local receive_limit_action; local igp_table
get disabled ${section}
get table ${section}
get igp_table ${section}
get template ${section}
get description ${section}
get passive ${section}
get import ${section}
get export ${section}
get source_address ${section}
get local_as ${section}
get neighbor_address ${section}
get neighbor_as ${section}
get import_limit ${section}
get import_limit_action ${section}
get export_limit ${section}
get export_limit_action ${section}
get receive_limit ${section}
get receive_limit_action ${section}
get_bool next_hop_self ${section}
get_bool next_hop_keep ${section}
get rr_client ${section}
get rr_cluster_id ${section}
writeToConfig "#${section} configuration:"
[ -n "${template}" ] && writeToConfig "protocol bgp ${section} from ${template} {" \
|| writeToConfig "protocol bgp ${section} {"
[ -n "${disabled}" ] && write_bool disabled ${disabled}
[ -n "${table}" ] && writeToConfig " table ${table};"
[ -n "${igp_table}" ] && writeToConfig " igp table ${igp_table};"
[ -n "${passive}" ] && writeToConfig " passive;" ${passive}
[ -n "${local_as}" ] && writeToConfig " local as ${local_as};"
[ -n "${source_address}" ] && writeToConfig " source address ${source_address};"
[ -n "${import}" ] && writeToConfig " import ${import};"
[ -n "${export}" ] && writeToConfig " export ${export};"
[ -n "${neighbor_address}" -a -n "${neighbor_as}" ] && writeToConfig " neighbor ${neighbor_address} as ${neighbor_as};"
if [ -n "${import_limit}" -a "${import_limit}" > "0" ]; then
[ -z "${import_limit_action}" ] && ${import_limit_action} = "warn"
writeToConfig " import limit ${import_limit} action ${import_limit_action};"
fi
if [ -n "${export_limit}" -a "${export_limit}" > "0" ]; then
[ -z "${export_limit_action}" ] && ${export_limit_action} = "warn"
writeToConfig " export limit ${export_limit} action ${export_limit_action};"
fi
if [ -n "${receive_limit}" -a "${receive_limit}" > "0" ]; then
[ -z "${receive_limit_action}" ] && ${receive_limit_action} = "warn"
writeToConfig " receive limit ${receive_limit} action ${receive_limit_action};"
fi
[ -n "${next_hop_self}" ] && write_bool " next hop self;" ${next_hop_self}
[ -n "${next_hop_keep}" ] && write_bool " next hop keep;" ${next_hop_keep}
[ -n "${rr_client}" ] && write_bool " rr client;" ${rr_client}
[ -n "${rr_cluster_id}" ] && writeToConfig " rr cluster id ${rr_cluster_id};"
writeToConfig "}"
writeToConfig " "
}
#Function: prepare_ospf_network $1
# $1 string $2 string
# This function gets each "ospf_network" protocol section in the UCI configuration, checks if its Area ID is the same as the one
# being configurated and finally sets the list of network ranges to be propagated, or not, by the OSPF protocol
# $1 is set as the ID of the action area of the internal networks.
# $2 is set as the ID of the current area being configurated.
prepare_ospf_networks() {
local section="$1"
local current_area="$2"
if [ "${section}" = "${current_area}" ]; then
writeToConfig " networks {"
config_list_foreach ${section} range range_list
config_list_foreach ${section} hidden_range hidden_range_list
writeToConfig " };"
fi
}
# Function: prepare_ospf_password $1 $2
prepare_ospf_passwords() {
local section="$1"
local current_interface="$2"
local interface; local passphrase
get interface $section
get passphrase $section
[ "current_interface" = "${interface}" ] && write ' password "$passphrase";' ${passphrase}
}
# Function: prepare_ospf_neighbors $1 $2
#prepare_ospf_neighbors() {
#}
# Function: prepare_ospf_interface $1 $2
prepare_ospf_interface() {
local section="$1"
local current_area="$2"
local area; local cost; local type; local hello; local priority; local retransmit; local authentication
get area ${section}
get cost ${section}
get type ${section}
get hello ${section}
get priority ${section}
get retransmit ${section}
if [ "${current_area}" = "${area}" ]; then
writeToConfig ' interface "$section" {'
write " cost ${cost};" ${cost}
write " hello ${hello};" ${hello}
write " type ${type};" ${type}
write " retransmit ${retransmit};" ${retransmit}
write " authentication ${authentication};" ${authentication}
config_foreach prepare_ospf_passwords "ospf_password" ${section}
# config_foreach prepare_ospf_neighbors "ospf_neighbor" $section
writeToConfig " };"
fi
}
# Function: prepare_ospf_area $1
prepare_ospf_area() {
local section="$1"
local instance; local stub; local default_cost
get instance ${section}
get stub ${section}
get default_cost ${section}
writeToConfig " area ${section} {"
if [ -n "${instance}" -a "${instance}" = "${section}" ]; then
[ -n "${stub}" -a "${stub}" = "1" ] && writeToConfig " stub yes;"
[ -n "${default_cost}" ] && writeToConfig " default cost ${default_cost};"
config_foreach prepare_ospf_networks "ospf_networks" ${section}
config_foreach prepare_ospf_interface "ospf_interface" ${section}
writeToConfig " };"
fi
}
# Function: prepare_ospf_instance $1
# $1 string
# This function gets each "ospf_area" protocol section in the UCI configuration and sets each option in the bird4.conf file.
# $1 is set as the ID of the current UCI ospf_area section.
prepare_ospf_instance() {
local section="$1"
local cfg1583compat; local tick
get cfg1583compat ${section}
get tick ${section}
writeToConfig "protocol ospf ${section} {"
[ -n "${cfg1583compat}" ] && cfg1583State="yes" || cfg1583State="no"
writeToConfig " rfc1583compat ${cfg1583State};"
[ -n "${tick}" ] && writeToConfig " tick ${tick};"
config_foreach prepare_ospf_area 'ospf_area'
writeToConfig "}"
}
# Function: gather_filters
# This function gets all the FILES under /filters folder and adds
# them into the config as %include elements on top of the file
# If there are no filters, the section will remain empty.
gather_filters() {
writeToConfig "#Filters Section:"
for filter in $(find /etc/${BIRD}/filters -type f); do
writeToConfig "include \"${filter}\";"
done
writeToConfig "#End of Filters --"
writeToConfig " "
}
# Function: gather_functions
# This function gets all the FILES under /functions folder and adds
# them into the config as %include elements on top of the file
# If there are no filters, the section will remain empty.
gather_functions() {
writeToConfig "#Functions Section:"
for func in $(find /etc/${BIRD}/functions -type f); do
writeToConfig "include \"${func}\";"
done
writeToConfig "#End of Functions --"
writeToConfig " "
}

View File

@ -1,6 +1,5 @@
--[[
Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
BGP/Bird integration with OpenWRT and QMP
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -18,45 +17,62 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
require("luci.sys")
local http = require "luci.http"
local uci = require "luci.model.uci"
local uciout = uci.cursor()
local uci = luci.model.uci.cursor()
-- Repeated Strings
local common_string = "Valid options are:<br />" .. "1. all (All the routes)<br />" .. "2. none (No routes)<br />" .. "3. filter <b>Your_Filter_Name</b> (Call a specific filter from any of the available in the filters files)"
local imp_string = "Set if the protocol must import routes.<br />" .. common_string
local exp_string = "Set if the protocol must export routes.<br />" .. common_string
m=Map("bird4", "Bird4 BGP protocol's configuration")
tab_templates = {}
uciout:foreach('bird4', 'bgp_template', function (s)
uci:foreach('bird4', 'bgp_template', function (s)
local name = s[".name"]
if (name ~= nil) then
table.insert(tab_templates, name)
end
end)
-- Section BGP Templates
--
-- BGP TEMPLATES
--
sect_templates = m:section(TypedSection, "bgp_template", "BGP Templates", "Configuration of the templates used in BGP instances.")
sect_templates.addremove = true
sect_templates.anonymous = false
disabled = sect_templates:option(Flag, "disabled", "Disabled", "Enable/Disable BGP Protocol")
disabled.optional=true
table = sect_templates:option(ListValue, "table", "Table", "Set the table used for BGP Routing")
table.optional=true
uciout:foreach("bird4", "table",
uci:foreach("bird4", "table",
function (s)
table:value(s.name)
end)
table:value("")
table.default = ""
import = sect_templates:option(Value, "import", "Import","")
igp_table = sect_templates:option(ListValue, "igp_table", "IGP Table", "Select the IGP Routing Table to use. Hint: usually the same table as BGP.")
igp_table.optional = true
uci:foreach("bird4", "table",
function(s)
igp_table:value(s.name)
end)
igp_table:value("")
igp_table.default = ""
import = sect_templates:option(Value, "import", "Import", imp_string)
import.optional=true
export = sect_templates:option(Value, "export", "Export", "")
export = sect_templates:option(Value, "export", "Export", exp_string)
export.optional=true
source_addr = sect_templates:option(Value, "source_address", "Source Address", "Source address for BGP routing. By default uses Router ID")
source_addr.optional = true
description = sect_templates:option(TextValue, "description", "Description", "Description of the current BGP instance")
description.optional = true
local_as = sect_templates:option(Value, "local_as", "Local AS", "")
local_as.optional = false
next_hop_self = sect_templates:option(Flag, "next_hop_self", "Next hop self", "Avoid next hop calculation and advertise own source address as next hop")
next_hop_self.default = nil
@ -73,68 +89,123 @@ rr_client.optional = true
rr_cluster_id = sect_templates:option(Value, "rr_cluster_id", "Route Reflector Cluster ID", "Identificator of the RR cluster. By default uses the Router ID")
rr_cluster_id.optional = true
import_limit = sect_templates:option(Value, "import_limit", "Routes import limit", "Specify an import route limit. By default is disabled '0'")
import_limit.default= "0"
import_limit.optional = true
import_trigger = sect_templates:option(Flag, "import_trigger", "Import Limit", "Enable Routes Import limit settings")
import_trigger.default = 0
import_trigger.rmempty = false
import_trigger.optional = false
import_limit = sect_templates:option(Value, "import_limit", "Routes import limit", "Specify an import route limit.")
import_limit:depends({import_trigger = "1"})
import_limit.rmempty = true
import_limit_action = sect_templates:option(ListValue, "import_limit_action", "Routes import limit action", "Action to take when import routes limit ir reached")
import_limit_action:depends({import_trigger = "1"})
import_limit_action:value("warn")
import_limit_action:value("block")
import_limit_action:value("disable")
import_limit_action:value("restart")
import_limit_action.default = "warn"
import_limit_action.optional = true
import_limit_action.rmempty = true
export_limit = sect_templates:option(Value, "export_limit", "Routes export limit", "Specify an export route limit. By default is disabled '0'")
export_limit.default="0"
export_limit.optional = true
export_trigger = sect_templates:option(Flag, "export_trigger", "Export Limit", "Enable Routes Export limit settings")
export_trigger.default = 0
export_trigger.rmempty = false
export_trigger.optional = false
export_limit = sect_templates:option(Value, "export_limit", "Routes export limit", "Specify an export route limit.")
export_limit:depends({export_trigger = "1"})
export_limit.rmempty = true
export_limit_action = sect_templates:option(ListValue, "export_limit_action", "Routes export limit action", "Action to take when export routes limit is reached")
export_limit_action:depends({export_trigger = "1"})
export_limit_action.rmempty = true
export_limit_action:value("warn")
export_limit_action:value("block")
export_limit_action:value("disable")
export_limit_action:value("restart")
export_limit_action.default = "warn"
export_limit_action.optional = true
receive_limit = sect_templates:option(Value, "receive_limit", "Routes received limit", "Specify a received route limit. By default is disabled '0'")
receive_limit.default="0"
receive_limit.optional = true
receive_trigger = sect_templates:option(Flag, "receive_trigger", "Received Limit", "Enable Routes Received Limit settings")
receive_trigger.default = 0
receive_trigger.rmempty = false
receive_trigger.optional = false
receive_limit = sect_templates:option(Value, "receive_limit", "Routes received limit", "Specify a received route limit.")
receive_limit:depends({receive_trigger = "1"})
receive_limit.rmempty = true
receive_limit_action = sect_templates:option(ListValue, "receive_limit_action", "Routes received limit action", "Action to take when received routes limit is reached")
receive_limit_action:depends({receive_trigger = "1"})
receive_limit_action:value("warn")
receive_limit_action:value("block")
receive_limit_action:value("disable")
receive_limit_action:value("restart")
receive_limit_action.default = "warn"
receive_limit_action.optional = true
local_address = sect_templates:option(Value, "local_address", "Local BGP address", "")
local_address.optional=true
local_as = sect_templates:option(Value, "local_as", "Local AS", "")
local_as.optional=true
-- Section BGP Instances:
receive_limit_action.rmempty= true
--
-- BGP INSTANCES
--
sect_instances = m:section(TypedSection, "bgp", "BGP Instances", "Configuration of the BGP protocol instances")
sect_instances.addremove = true
sect_instances.anonymous = false
templates = sect_instances:option(ListValue, "template", "Templates", "Available BGP templates")
disabled = sect_instances:option(Flag, "disabled", "Disabled", "Enable/Disable BGP Protocol")
disabled.optional = false
disabled.rmempty = false
disabled.default = nil
uciout:foreach("bird4", "bgp_template",
templates = sect_instances:option(ListValue, "template", "Templates", "Available BGP templates")
uci:foreach("bird4", "bgp_template",
function(s)
templates:value(s[".name"])
end)
templates:value("")
source_addr = sect_instances:option(Value, "source_address", "Source Address", "Source address for BGP routing. By default uses Router ID")
source_addr.optional = true
description = sect_instances:option(TextValue, "description", "Description", "Description of the current BGP instance")
description.optional = true
table = sect_instances:option(ListValue, "table", "Table", "Set the table used for BGP Routing")
table.optional=true
uci:foreach("bird4", "table",
function (s)
table:value(s.name)
end)
table:value("")
table.default = ""
igp_table = sect_instances:option(ListValue, "igp_table", "IGP Table", "Select the IGP Routing Table to use. Hint: usually the same table as BGP.")
igp_table.optional = true
uci:foreach("bird4", "table",
function(s)
igp_table:value(s.name)
end)
igp_table:value("")
igp_table.default = ""
passive = sect_instances:option(Flag, "passive", "Passive", "Disable automatic initialization of outgoing connections.")
passive.optional=true
passive.rmempty = false
passive.default = nil
import = sect_instances:option(Value, "import", "Import", imp_string)
import.optional=true
export = sect_instances:option(Value, "export", "Export", exp_string)
export.optional=true
source_address = sect_instances:option(Value, "source_address", "Source Address", "Source address for BGP routing. By default uses Router ID")
source_address.optional = true
local_as = sect_instances:option(Value, "local_as", "Local AS", "")
local_as.optional=true
neighbor_address = sect_instances:option(Value, "neighbor_address", "Neighbor IP Address", "")
neighbor_address.optional = false
neighbor_as = sect_instances:option(Value, "neighbor_as", "Neighbor AS", "")
neighbor_as.optional = false
next_hop_self = sect_instances:option(Flag, "next_hop_self", "Next hop self", "Avoid next hop calculation and advertise own source address as next hop")
next_hop_self.default = nil
next_hop_self.optional = true
@ -150,90 +221,62 @@ rr_client.optional = true
rr_cluster_id = sect_instances:option(Value, "rr_cluster_id", "Route Reflector Cluster ID", "Identificator of the RR cluster. By default uses the Router ID")
rr_cluster_id.optional = true
import_limit = sect_instances:option(Value, "import_limit", "Routes import limit", "Specify an import route limit. By default is disabled '0'")
import_limit.default="0"
import_limit.optional = true
import_trigger = sect_instances:option(Flag, "import_trigger", "Import Limit", "Enable Routes Import limit settings")
import_trigger.default = 0
import_trigger.rmempty = false
import_trigger.optional = false
import_limit = sect_instances:option(Value, "import_limit", "Routes import limit", "Specify an import route limit.")
import_limit:depends({import_trigger = "1"})
import_limit.rmempty = true
import_limit_action = sect_instances:option(ListValue, "import_limit_action", "Routes import limit action", "Action to take when import routes limit ir reached")
import_limit_action:depends({import_trigger = "1"})
import_limit_action:value("warn")
import_limit_action:value("block")
import_limit_action:value("disable")
import_limit_action:value("restart")
import_limit_action.default = "warn"
import_limit_action.optional = true
import_limit_action.rmempty = true
export_limit = sect_instances:option(Value, "export_limit", "Routes export limit", "Specify an export route limit. By default is disabled '0'")
export_limit.default="0"
export_limit.optional = true
export_trigger = sect_instances:option(Flag, "export_trigger", "Export Limit", "Enable Routes Export limit settings")
export_trigger.default = 0
export_trigger.rmempty = false
export_trigger.optional = false
export_limit = sect_instances:option(Value, "export_limit", "Routes export limit", "Specify an export route limit.")
export_limit:depends({export_trigger = "1"})
export_limit.rmempty = true
export_limit_action = sect_instances:option(ListValue, "export_limit_action", "Routes export limit action", "Action to take when export routes limit is reached")
export_limit_action:depends({export_trigger = "1"})
export_limit_action:value("warn")
export_limit_action:value("block")
export_limit_action:value("disable")
export_limit_action:value("restart")
export_limit_action.default = "warn"
export_limit_action.optional = true
export_limit_action.rmempty= true
receive_limit = sect_instances:option(Value, "receive_limit", "Routes received limit", "Specify a received route limit. By default is disabled '0'")
receive_limit.default="0"
receive_limit.optional = true
receive_trigger = sect_instances:option(Flag, "receive_trigger", "Received Limit", "Enable Routes Received Limit settings")
receive_trigger.default = 0
receive_trigger.rmempty = false
receive_trigger.optional = false
receive_limit = sect_instances:option(Value, "receive_limit", "Routes received limit", "Specify a received route limit.")
receive_limit:depends({receive_trigger = "1"})
receive_limit.rmempty = true
receive_limit_action = sect_instances:option(ListValue, "receive_limit_action", "Routes received limit action", "Action to take when received routes limit is reached")
receive_limit_action:depends({receive_trigger = "1"})
receive_limit_action:value("warn")
receive_limit_action:value("block")
receive_limit_action:value("disable")
receive_limit_action:value("restart")
receive_limit_action.default = "warn"
receive_limit_action.optional = true
receive_limit_action.rmempty= true
neighbor_address = sect_instances:option(Value, "neighbor_address", "Neighbor IP Address", "")
neighbor_as = sect_instances:option(Value, "neighbor_as", "Neighbor AS", "")
disabled = sect_instances:option(Flag, "disabled", "Disabled", "Enable/Disable BGP Protocol")
disabled.optional=true
disabled.default=nil
table = sect_instances:option(ListValue, "table", "Table", "Set the table used for BGP Routing")
table.optional=true
uciout:foreach("bird4", "table",
function (s)
table:value(s.name)
end)
table:value("")
import = sect_instances:option(Value, "import", "Import","")
import.optional=true
export = sect_instances:option(Value, "export", "Export", "")
export.optional=true
local_address = sect_instances:option(Value, "local_address", "Local BGP address", "")
local_address.optional=true
local_as = sect_instances:option(Value, "local_as", "Local AS", "")
local_as.optional=true
-- Section BGP Filters
sect_filters = m:section(TypedSection, "filter", "BGP Filters", "Filters of the BGP instances")
sect_filters.addremove = true
sect_filters.anonymous = false
sect_filters:depends("type", "bgp")
instance = sect_filters:option(ListValue, "instance", "BGP instance", "Filter's BGP instance")
instance:depends("type", "bgp")
uciout:foreach("bird4", "bgp",
function (s)
instance:value(s[".name"])
end)
type = sect_filters:option(Value, "type", "Filter type", "")
type.default = "bgp"
path = sect_filters:option(Value, "file_path", "Filter's file path", "Path to the Filter's file")
path:depends("type", "bgp")
function m.on_commit(self,map)
luci.sys.call('/etc/init.d/bird4 stop; /etc/init.d/bird4 start')
luci.sys.exec('/etc/init.d/bird4 restart')
end
return m

View File

@ -0,0 +1,77 @@
--[[
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]--
local fs = require "nixio.fs"
local filters_dir = "/etc/bird4/filters/"
local lock_file = "/etc/bird4/filter_lock"
m = SimpleForm("bird4", "Bird4 Filters", "<b>INFO:</b> New files are created using Timestamps.<br />In order to make it easier to handle, use SSH to connect to your terminal and rename those files.<br />If your file is not correctly shown in the list, please, refresh your browser.")
s = m:section(SimpleSection)
files = s:option(ListValue, "Files", "Filter Files:")
local new_filter = filters_dir .. os.date("filter-%Y%m%d-%H%M")
-- New File Entry
files:value(new_filter, "New File (".. new_filter .. ")")
files.default = new_filter
local i, file_list = 0, { }
for filename in io.popen("find " .. filters_dir .. " -type f"):lines() do
i = i + 1
files:value(filename, filename)
end
ld = s:option(Button, "_load", "Load File")
ld.inputstyle = "reload"
st_file = s:option(DummyValue, "_stfile", "Editing file:")
function st_file.cfgvalue(self, section)
if ld:formvalue(section) then
fs.writefile(lock_file, files:formvalue(section))
return files:formvalue(section)
else
fs.writefile(lock_file, "")
return ""
end
end
area = s:option(Value, "_filters")
area.template = "bird4/tvalue"
area.rows = 30
function area.cfgvalue(self,section)
if ld:formvalue(section) then
local contents = fs.readfile(files:formvalue(section))
if contents then
return contents
else
return ""
end
else
return ""
end
end
function area.write(self, section)
local locked_file = fs.readfile(lock_file)
if locked_file and not ld:formvalue(section) then
local text = self:formvalue(section):gsub("\r\n?", "\n")
fs.writefile(locked_file, text)
fs.writefile(lock_file, "")
end
end
return m

View File

@ -0,0 +1,77 @@
--[[
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]--
local fs = require "nixio.fs"
local functions_dir = "/etc/bird4/functions/"
local lock_file = "/etc/bird4/function_lock"
m = SimpleForm("bird4", "Bird4 Functions", "<b>INFO:</b> New files are created using Timestamps.<br />In order to make it easier to handle, use SSH to connect to your terminal and rename those files.<br />If your file is not correctly shown in the list, please, refresh your browser.")
s = m:section(SimpleSection)
files = s:option(ListValue, "Files", "Function Files:")
local new_function = functions_dir .. os.date("function-%Y%m%d-%H%M")
-- New File Entry
files:value(new_function, "New File (".. new_function .. ")")
files.default = new_function
local i, file_list = 0, { }
for filename in io.popen("find " .. functions_dir .. " -type f"):lines() do
i = i + 1
files:value(filename, filename)
end
ld = s:option(Button, "_load", "Load File")
ld.inputstyle = "reload"
st_file = s:option(DummyValue, "_stfile", "Editing file:")
function st_file.cfgvalue(self, section)
if ld:formvalue(section) then
fs.writefile(lock_file, files:formvalue(section))
return files:formvalue(section)
else
fs.writefile(lock_file, "")
return ""
end
end
area = s:option(Value, "_functions")
area.template = "bird4/tvalue"
area.rows = 30
function area.cfgvalue(self,section)
if ld:formvalue(section) then
local contents = fs.readfile(files:formvalue(section))
if contents then
return contents
else
return ""
end
else
return ""
end
end
function area.write(self, section)
local locked_file = fs.readfile(lock_file)
if locked_file and not ld:formvalue(section) then
local text = self:formvalue(section):gsub("\r\n?", "\n")
fs.writefile(locked_file, text)
fs.writefile(lock_file, "")
end
end
return m

View File

@ -1,6 +1,5 @@
--[[
Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
BGP/Bird integration with OpenWRT and QMP
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -18,20 +17,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
require("luci.sys")
local http = require "luci.http"
local uci = require "luci.model.uci"
local uciout = uci.cursor()
local uci = luci.model.uci.cursor()
-- Repeated Strings
local common_string = "Valid options are:<br />" .. "1. all (All the routes)<br />" .. "2. none (No routes)<br />" .. "3. filter <b>Your_Filter_Name</b> (Call a specific filter from any of the available in the filters files)"
local imp_string = "Set if the protocol must import routes.<br />" .. common_string
local exp_string = "Set if the protocol must export routes.<br />" .. common_string
m=Map("bird4", "Bird4 general protocol's configuration.")
-- Optional parameters lists
local protoptions = {
{["name"]="table", ["help"]="Auxiliar table for routing", ["depends"]={"static","kernel"}},
{["name"]="import", ["help"]="Set if the protocol must import routes", ["depends"]={"kernel"}},
{["name"]="export", ["help"]="Set if the protocol must export routes", ["depends"]={"kernel"}},
{["name"]="import", ["help"]=imp_string, ["depends"]={"kernel"}},
{["name"]="export", ["help"]=exp_string, ["depends"]={"kernel"}},
{["name"]="scan_time", ["help"]="Time between scans", ["depends"]={"kernel","device"}},
{["name"]="kernel_table", ["help"]="Set which table must be used as auxiliar kernel table", ["depends"]={"kernel"}},
{["name"]="learn", ["help"]="Learn routes", ["depends"]={"kernel"}},
{["name"]="persist", ["help"]="Store routes. After a restart, routes will be still configured", ["depends"]={"kernel"}}
{["name"]="persist", ["help"]="Store routes. After a restart, routes willstill be configured", ["depends"]={"kernel"}}
}
local routeroptions = {
@ -42,16 +45,15 @@ local routeroptions = {
{["name"]="ip",["help"]="",["depends"]={"recursive"}}
}
--
-- KERNEL PROTOCOL
--
sect_kernel_protos = m:section(TypedSection, "kernel", "Kernel options", "Configuration of the kernel protocols. First Instance MUST be Primary table (no table or kernel_table fields).")
sect_kernel_protos.addremove = true
sect_kernel_protos.anonymous = false
-- Default kernel parameters
disabled = sect_kernel_protos:option(Flag, "disabled", "Disabled", "If this option is true, the protocol will not be configured.")
disabled.default=0
@ -64,11 +66,12 @@ for _,o in ipairs(protoptions) do
value = sect_kernel_protos:option(Flag, o.name, translate(o.name), translate(o.help))
elseif o.name == "table" then
value = sect_kernel_protos:option(ListValue, o.name, translate(o.name), translate(o.help))
uciout:foreach("bird4", "table",
uci:foreach("bird4", "table",
function (s)
value:value(s.name)
end)
value:value("")
value.default = ""
else
value = sect_kernel_protos:option(Value, o.name, translate(o.name), translate(o.help))
end
@ -80,10 +83,10 @@ for _,o in ipairs(protoptions) do
end
end
--
-- DEVICE PROTOCOL
--
sect_device_protos = m:section(TypedSection, "device", "Device options", "Configuration of the device protocols.")
sect_device_protos.addremove = true
sect_device_protos.anonymous = false
@ -105,55 +108,112 @@ for _,o in ipairs(protoptions) do
end
end
end
--
-- PIPE PROTOCOL
--
sect_pipe_protos = m:section(TypedSection, "pipe", "Pipe options", "Configuration of the Pipe protocols.")
sect_pipe_protos.addremove = true
sect_pipe_protos.anonymous = false
-- Default Pipe parameters
disabled = sect_pipe_protos:option(Flag, "disabled", "Disabled", "If this option is true, the protocol will not be configured. This protocol will connect the configured 'Table' to the 'Peer Table'.")
disabled.default=0
table = sect_pipe_protos:option(ListValue, "table", "Table", "Select the Primary Table to connect.")
table.optional = false
uci:foreach("bird4", "table",
function (s)
table:value(s.name)
end)
table:value("")
table.default = ""
peer_table = sect_pipe_protos:option(ListValue, "peer_table", "Peer Table", "Select the Secondary Table to connect.")
table.optional = false
uci:foreach("bird4", "table",
function (s)
peer_table:value(s.name)
end)
peer_table:value("")
peer_table.default = ""
mode = sect_pipe_protos:option(ListValue, "mode", "Mode", "Select <b>transparent</b> to retransmit all routes and their attributes<br />Select <b>opaque</b> to retransmit optimal routes (similar to what other protocols do)")
mode.optional = false
mode:value("transparent")
mode:value("opaque")
mode.default = "transparent"
import = sect_pipe_protos:option(Value, "import", "Import",imp_string)
import.optional=true
export = sect_pipe_protos:option(Value, "export", "Export", exp_string)
export.optional=true
--
-- DIRECT PROTOCOL
--
sect_direct_protos = m:section(TypedSection, "direct", "Direct options", "Configuration of the Direct protocols.")
sect_direct_protos.addremove = true
sect_direct_protos.anonymous = false
-- Default Direct parameters
disabled = sect_direct_protos:option(Flag, "disabled", "Disabled", "If this option is true, the protocol will not be configured. This protocol will connect the configured 'Table' to the 'Peer Table'.")
disabled.optional = false
disabled.default = 0
interface = sect_direct_protos:option(Value, "interface", "Interfaces", "By default Direct will generate device routes for all the interfaces. To restrict this behaviour, select a number of patterns to match your desired interfaces:" .. "<br />" .. "1. All the strings <b>MUST</b> be quoted: \"pattern\"" .. "<br />" .. "2. Use * (star) to match patterns: \"eth*\" (<b>include</b> all eth... interfaces)" .. "<br />" .. "3. You can add \"-\" (minus) to exclude patterns: \"-em*\" (<b>exclude</b> all em... interfaces)." .. "<br />" .. "4. Separate several patterns using , (coma): \"-em*\", \"eth*\" (<b>exclude</b> em... and <b>include</b> all eth... interfaces).")
interface.optional = false
interface.default = "\"*\""
--
-- STATIC PROTOCOL
--
sect_static_protos = m:section(TypedSection, "static", "Static options", "Configuration of the static protocols.")
sect_static_protos.addremove = true
sect_static_protos.anonymous = false
-- Default kernel parameters
disabled = sect_static_protos:option(Flag, "disabled", "Disabled", "If this option is true, the protocol will not be configured.")
disabled.default=0
-- Optional parameters
for _,o in ipairs(protoptions) do
if o.name ~= nil then
for _, d in ipairs(o.depends) do
if d == "static" then
if o.name == "table" then
value = sect_static_protos:option(ListValue, o.name, translate(o.name), translate(o.help))
uciout:foreach("bird4", "table",
function (s)
value:value(s.name)
end)
value:value("")
else
value = sect_static_protos:option(Value, o.name, translate(o.name), translate(o.help))
end
value.optional = true
value.rmempty = true
end
end
end
if o.name ~= nil then
for _, d in ipairs(o.depends) do
if d == "static" then
if o.name == "table" then
value = sect_static_protos:option(ListValue, o.name, translate(o.name), translate(o.help))
uci:foreach("bird4", "table",
function (s)
value:value(s.name)
end)
value:value("")
value.default = ""
else
value = sect_static_protos:option(Value, o.name, translate(o.name), translate(o.help))
end
value.optional = true
value.rmempty = true
end
end
end
end
--
-- ROUTES FOR STATIC PROTOCOL
--
sect_routes = m:section(TypedSection, "route", "Routes configuration", "Configuration of the routes used in static protocols.")
sect_routes.addremove = true
sect_routes.anonymous = true
instance = sect_routes:option(ListValue, "instance", "Route instance", "")
i = 0
uciout:foreach("bird4", "static",
uci:foreach("bird4", "static",
function (s)
instance:value(s[".name"])
end)
@ -177,15 +237,19 @@ listVia:depends("type", "multipath")
listVia.optional=false
listVia.datatype = "ip4addr"
attribute = sect_routes:option(Value, "attribute", "Attribute", "Types are: unreachable, prohibit and blackhole")
attribute = sect_routes:option(ListValue, "attribute", "Attribute", "")
attribute:depends("type", "special")
attribute:value("unreachable")
attribute:value("prohibit")
attribute:value("blackhole")
iface = sect_routes:option(ListValue, "iface", "Interface", "")
iface:depends("type", "iface")
uciout:foreach("wireless", "wifi-iface",
uci:foreach("network", "interface",
function(section)
iface:value(section[".name"])
if section[".name"] ~= "loopback" then
iface:value(section[".name"])
end
end)
ip = sect_routes:option(Value, "ip", "IP address", "")
@ -193,8 +257,7 @@ ip:depends("type", "ip")
ip.datatype = [[ or"ip4addr", "ip6addr" ]]
function m.on_commit(self,map)
luci.sys.call('/etc/init.d/bird4 stop; /etc/init.d/bird4 start')
luci.sys.exec('/etc/init.d/bird4 restart')
end
return m

View File

@ -1,6 +1,5 @@
--[[
Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
BGP/Bird integration with OpenWRT and QMP
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -30,7 +29,7 @@ s_bird_uci.addremove = False
uuc = s_bird_uci:option(Flag, "use_UCI_config", "Use UCI configuration", "Use UCI configuration instead of the /etc/bird4.conf file")
ucf = s_bird_uci:option(Value, "UCI_config_File", "UCI File", "Specify the file to place the UCI-translated configuration")
ucf = s_bird_uci:option(Value, "UCI_config_file", "UCI File", "Specify the file to place the UCI-translated configuration")
ucf.default = "/tmp/bird4.conf"
-- Named Section: "table"
@ -71,7 +70,7 @@ d:value("events","Events")
d:value("packets","Packets")
function m.on_commit(self,map)
luci.sys.call('/etc/init.d/bird4 stop; /etc/init.d/bird4 start')
luci.sys.exec('/etc/init.d/bird4 restart')
end
return m

View File

@ -0,0 +1,53 @@
--[[
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]--
local sys = require "luci.sys"
m = SimpleForm("bird4", "Bird4 Daemon Status Page", "This page let you Start, Stop, Restart and check Bird4 Service Status.")
m.reset = false
m.submit = false
s = m:section(SimpleSection)
start = s:option(Button, "_start", "Start Bird4 Daemon:")
start.inputtitle = " Start "
start.inputstyle = "apply"
stop = s:option(Button, "_stop", "Stop Bird4 Daemon:")
stop.inputtitle = " Stop "
stop.inputstyle = "remove"
restart = s:option(Button, "_restart", "Restart Bird4 Daemon:")
restart.inputtitle = "Restart"
restart.inputstyle = "reload"
output = s:option(DummyValue, "_value", "Service Status")
function output.cfgvalue(self, section)
local ret = ""
if start:formvalue(section) then
ret = sys.exec("/etc/init.d/bird4 start_quiet")
elseif stop:formvalue(section) then
ret = sys.exec("/etc/init.d/bird4 stop_quiet")
elseif restart:formvalue(section) then
ret = sys.exec("/etc/init.d/bird4 restart_quiet")
else
ret = sys.exec("/etc/init.d/bird4 status_quiet")
end
return ret
end
return m

View File

@ -0,0 +1,33 @@
#!/bin/sh
# This UCI-Defaults script will MOVE any pre-existing filter
# stored in a file and configured as an UCI item (deprecated)
# The script will try to match any "filter" Section, get its
# "file_path" property and move the file (if exists) to the
# new (v0.3+) default location: /etc/bird{4|6}/filters
[ $# -ne 1 ] && exit 1
BIRD="$1"
. /lib/functions.sh
# This function will move an existing folder configured on
# Bird as a "filter" to filters' folder.
mv_filter() {
local section="$1"
local file_path
config_get file_path ${section} file_path
if [ -f ${file_path} ]; then
mv ${file_path} /etc/${BIRD}/filters/
fi
uci delete ${BIRD}.${section}
}
if [ -f /etc/config/${BIRD} ]; then
config_load ${BIRD}
config_foreach mv_filter 'filter'
uci commit ${BIRD}
fi
exit 0

View File

@ -0,0 +1,13 @@
#!/bin/sh
[ $# -ne 1 ] && exit 1
BIRD=$1
EXC=`mount -t overlayfs | grep overlayfs -c`
[ $EXC > 0 ] && rm -r /etc/init.d/${BIRD} || mv /etc/init.d/${BIRD} /etc/${BIRD}/init.d/${BIRD}.orig
ln -s /etc/${BIRD}/init.d/${BIRD} /etc/init.d/${BIRD}
exit 0

View File

@ -1,7 +0,0 @@
#!/bin/sh
EXC=`mount -t overlayfs | grep overlayfs -c`
[ $EXC > 0 ] && rm -r /etc/init.d/bird4 || mv /etc/init.d/bird4 /etc/bird4/init.d/bird4.orig
ln -s /etc/bird4/init.d/bird4 /etc/init.d/bird4

View File

@ -0,0 +1,41 @@
<%-
-- Only populate textarea through XHR.poll
-- "refresh" is present in the URL (.../log?refresh=1)
if luci.http.formvalue("refresh") then
-- Force HTTP Contents to be "text/plain"
luci.http.prepare_content("text/plain")
local sys = require("luci.sys")
local uci = require "luci.model.uci".cursor()
-- Get Log File from Bird's configuration or leave it empty.
local log_file = uci:get("bird4", "global", "log_file") or ""
local log_size = ""
if log_file then
log_size = sys.exec("du -h " .. log_file .. " | awk '{print $1}'")
-- Gathering last 30 lines of the Log File.
lf = sys.exec("tail -n30 " .. log_file):gsub("\r\n?", "\n")
end
-- Write File used and its contents.
luci.http.write("Using Log File: " .. log_file .. " - File Size: " .. log_size .. "\n" .. lf)
-- Avoid printing the rest of the page (return only text log data)
return
end
-%>
<%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
// Refresh page each second. Use "refresh=1" as trigger.
XHR.poll(1, '<%=url('admin/network/bird4/log')%>', { refresh: 1 }, function(xhrInstance) {
var area = document.getElementById('log')
area.value = xhrInstance.responseText;
});
//]]></script>
<textarea readonly="readonly" style="width: 100%" wrap="on" rows="32" id="log"><%=lf:pcdata()%></textarea>
<%+footer%>

View File

@ -0,0 +1,5 @@
<%+cbi/valueheader%>
<textarea class="cbi-input-textarea" <% if not self.size then %> style="width: 100%; font: normal 11pt 'Courier New'"<% else %> cols="<%=self.size%>"<% end %> data-update="change"<%= attr("name", cbid) .. attr("id", cbid) .. ifattr(self.rows, "rows") .. ifattr(self.wrap, "wrap") .. ifattr(self.readonly, "readonly") %>>
<%-=pcdata(self:cfgvalue(section))-%>
</textarea>
<%+cbi/valuefooter%>

View File

@ -1,5 +1,4 @@
# Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
# BGP/Bird integration with OpenWRT and QMP
# Copyright (C) 2014-2017 Eloi Carbo <eloicaso@openmailbox.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -18,14 +17,14 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
BIRD:=bird6
PKG_NAME:=$(BIRD)-openwrt
PKG_RELEASE:=0.2
BIRD := bird6
PKG_NAME := $(BIRD)-openwrt
PKG_VERSION := 0.3
PKG_RELEASE := 1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_LICENSE:=GPL-3.0+
uci:=$(BIRD)-uci
luci:=luci-app-$(BIRD)
PKG_LICENSE := GPL-3.0+
uci := $(BIRD)-uci
luci := luci-app-$(BIRD)
include $(INCLUDE_DIR)/package.mk
@ -40,7 +39,7 @@ define Package/$(uci)
CATEGORY:=Network
SUBMENU:=Routing and Redirection
MAINTAINER:=Eloi Carbo <eloicaso@openmailbox.org>
URL:=https://github.com/eloicaso/bird6-openwrt/
URL:=https://github.com/eloicaso/bird-openwrt/
DEPENDS:=+$(BIRD) +libuci +uci
endef
@ -48,33 +47,42 @@ define Package/$(uci)/description
$(BIRD) UCI integration module
endef
define Package/$(uci)/conffiles
/etc/config/$(BIRD)
endef
define Package/$(uci)/install
$(INSTALL_DIR) $(1)/etc/$(BIRD)/init.d
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_BIN) ./src/init.d/$(BIRD) $(1)/etc/$(BIRD)/init.d/
$(CP) ./src/uci-defaults/$(uci)-install-init.d $(1)/etc/$(BIRD)/init.d/
$(CP) ./src/config/$(BIRD) $(1)/etc/config/
$(INSTALL_DIR) $(1)/etc/$(BIRD)/filters
$(INSTALL_DIR) $(1)/etc/$(BIRD)/functions
$(INSTALL_BIN) ./src/init.d/$(BIRD)* $(1)/etc/$(BIRD)/init.d/
$(CP) ./src/uci-defaults/* $(1)/etc/$(BIRD)/init.d/
$(INSTALL_CONF) ./src/config/$(BIRD) $(1)/etc/config/
endef
define Package/$(uci)/postinst
#!/bin/sh
if [ -z $${IPKG_INSTROOT} ]; then
( . /etc/bird6/init.d/bird6-uci-install-init.d ) && rm -f /etc/bird6/init.d/bird6-uci-install-init.d
fi
if [ -z "$${IPKG_INSTROOT}" ]; then
( . /etc/$(BIRD)/init.d/bird-uci-install-init.d $(BIRD) ) && rm -f /etc/$(BIRD)/init.d/bird-uci-install-init.d
( . /etc/$(BIRD)/init.d/99-relocate-filters $(BIRD) ) && rm -f /etc/$(BIRD)/init.d/99-relocate-filters
if [ -f /etc/sysupgrade.conf ] && ! grep $(BIRD) /etc/sysupgrade.conf; then
echo /etc/config/$(BIRD) >> /etc/sysupgrade.conf
echo /etc/$(BIRD)/filters/ >> /etc/sysupgrade.conf
echo /etc/$(BIRD)/functions/ >> /etc/sysupgrade.conf
fi
fi
endef
$(eval $(call BuildPackage,$(uci)))
define Package/$(luci)
TITLE:=LuCI support for $(BIRD)
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
MAINTAINER:=Eloi Carbo <eloicaso@openmailbox.org>
URL:=https://github.com/eloicaso/bird6-openwrt/
URL:=https://github.com/eloicaso/bird-openwrt/
DEPENDS:=+$(BIRD)-uci +luci-base
endef
@ -85,8 +93,10 @@ endef
define Package/$(luci)/install
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/$(BIRD)/
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/view/$(BIRD)/
$(CP) ./src/model/* $(1)/usr/lib/lua/luci/model/cbi/$(BIRD)/
$(CP) ./src/controller/* $(1)/usr/lib/lua/luci/controller/
$(CP) ./src/view/* $(1)/usr/lib/lua/luci/view/$(BIRD)/
endef
$(eval $(call BuildPackage,$(luci)))

View File

@ -2,7 +2,6 @@ config bird 'bird'
option use_UCI_config '1'
#Caution! Enabling this option, Bird will translate this
#UCI file and use it instead of /etc/bird6.conf
option UCI_config_file '/tmp/bird6.conf'
#If you enable useUCIconfig, UCIconfigFile will be Bird's
#configuration file location.
@ -11,10 +10,9 @@ config global 'global'
option log_file '/tmp/bird6.log'
option log 'all'
option debug 'off'
option router_id 'fc00::1:5'
option listen_bgp_addr 'fc00::1:5'
option listen_bgp_port '179'
option listen_bgp_dual '1'
# This option is set up because is mandatory for Bird6.
# Change it to your IPv4 Address or a HEX value.
option router_id '0xCAFEBABE'
config table
option name 'aux'
@ -36,45 +34,3 @@ config device device1
config static static1
option table 'aux'
option disabled '0'
config bgp bgp1
option template 'bgp_common'
option description 'Description of the BGP instance'
option neighbor_address 'fc00::1:5'
option neighbor_as '65530'
option next_hop_self '0'
option next_hop_keep '0'
option rr_client '1'
option rr_cluster_id 'fc00::1:5'
config bgp_template bgp_common
option table 'aux'
option import 'all'
option export 'all'
option local_address '2001:B30:1000:19::2'
option local_as '65001'
option import_limit '100'
option import_limit_action 'warn'
option export_limit '100'
option export_limit_action 'warn'
option receive_limit '100'
option receive_limit_action 'warn'
option disabled '0'
config route
option instance 'static1'
option type 'router'
option prefix '2001:db8:0:f103::/64'
option via 'fe80::225:90ff:fe97:a718'
config route
option instance 'static1'
option type 'special'
option prefix '2001:db8:0:f101::/128'
option attribute 'unreachable'
config route
option instance 'static1'
option type 'iface'
option prefix '2001:db8:0:f101::1111/128'
option iface 'eth0'

View File

@ -1,6 +1,5 @@
--[[
Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
BGP/Bird integration with OpenWRT and QMP
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -19,9 +18,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
module("luci.controller.bird6", package.seeall)
function index()
entry({"admin","network","bird6"}, cbi("bird6/overview"), "Bird6", 1).dependent=false
entry({"admin","network","bird6","overview"}, cbi("bird6/overview"), "Overview", 2).dependent=false
entry({"admin","network","bird6","proto_general"}, cbi("bird6/gen_proto"), "General protocols", 3).dependent=false
entry({"admin","network","bird6","proto_bgp"}, cbi("bird6/bgp_proto"), "BGP Protocol", 4).dependent=false
end
entry({"admin","network","bird6"},
alias("admin","network","bird6","status"),
_("Bird6"), 0)
entry({"admin", "network", "bird6", "status"},
cbi("bird6/status"),
_("Status"), 0).leaf = true
entry({"admin","network","bird6","log"},
template("bird6/log"),
_("Log"), 1).leaf = true
entry({"admin","network","bird6","overview"},
cbi("bird6/overview"),
_("Overview"), 2).leaf = true
entry({"admin","network","bird6","proto_general"},
cbi("bird6/gen_proto"),
_("General protocols"), 3).leaf = true
entry({"admin","network","bird6","proto_bgp"},
cbi("bird6/bgp_proto"),
_("BGP Protocol"), 4).leaf = true
entry({"admin","network","bird6","filters"},
cbi("bird6/filters"),
_("Filters"), 5).leaf = true
entry({"admin","network","bird6","functions"},
cbi("bird6/functions"),
_("Functions"), 6).leaf = true
end

View File

@ -1,7 +1,6 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
# BGP/Bird integration with OpenWRT and QMP
# Copyright (C) 2014-2017 - Eloi Carbo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -17,405 +16,210 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Extra Service Function to get the Status of the Service
# This complements /etc/rc.common functions
# Commands ending with *_quiet are meant to be ran in Luci. These
# scripts' return minimal output.
EXTRA_COMMANDS="status start_quiet stop_quiet restart_quiet status_quiet"
EXTRA_HELP=" status Returns service status"
BIRD="bird6"
BIRD_CONFIG="/etc/$BIRD.conf"
BIRD_CONFIG="/etc/${BIRD}.conf"
BIRD_LOG="/var/log/${BIRD}.log"
BIRD_ERR="/tmp/${BIRD}.err"
START=99
STOP=10
SERVICE_DAEMONIZE=1
SERVICE_USE_PID=1
SERVICE_PID_FILE="/var/run/$BIRD.pid"
SERVICE_PID_FILE="/var/run/${BIRD}.pid"
BIRD_BIN="/usr/sbin/$BIRD"
# Function: writeToConfig $1
# $1 string.
# Allows to write in the $BIRD_CONFIG file, the string $1. This function does not check the $1 string.
# Example: writeToConfig "value: $N"
writeToConfig() {
echo "$1" >> $BIRD_CONFIG
}
# Function: write $1 $2
# $1 string. $2 string.
# This function checks if $2 is empty. If not, it writes the string $1 in the $BIRD_CONFIG file.
# Use write function to check if $1, value found inside $2, is not empty and can be written in the configuration file.
# Example:
N=""; write "value: $N" $N;
write() {
[ -n "$2" ] && writeToConfig "$1"
}
#Function: write_bool $1 $2
# $1 string; $2 boolean
# This function checks if $2 is true or false and write the $1 string into $BIRD_CONFIG file.
# The function writes a # before the $2 string if its false.
# Example: local N=0; write_bool $N
write_bool() {
[ "$2" == 0 ] && writeToConfig "# $1;" || writeToConfig " $1;"
}
# Function: get $1 $2
# $1 string. $2 string
# This function uses the external UCI function "config_get $result $section $option" to obtain a string value from UCI config file.
# To use this function, use the same name of the UCI option for the variable.
# Example: UCI (option id 'abcd'); local id; get id $section
get() {
config_get $1 $2 $1
}
# Function: get_bool $1 $2
# $1 boolean. $2 string
# This function uses the external UCI function "config_get_bool $result $section $option" to obtain a boolean value from UCI config file.
# To use this function, use the same name of the UCI option for the variable $1.
# Example: UCI (option use_ipv6 '1'); local use_ipv6; get use_ipv6 $section
get_bool() {
config_get_bool $1 $2 $1
}
# Function: multipath_list $1
# $1 string
# This function writes the $1 string in the multipath routes.
multipath_list() {
write " via $1" $1
}
# Function: prepare_tables $1
# $1 string
# This function gets each "table" section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI table section
prepare_tables() {
local section="$1"; local name
get name $section
write "table $name;" $name
}
# Function: prepare_global $1
# $1 string
# This function gets each "global" section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI global section. prepare_global is the first configuration set in the bird6.conf and removes the old file.
prepare_global () {
local section="$1"
local log_file; local log; local debug; local router_id; local table; local listen_bgp_addr; local listen_bgp_port; local listen_bgp_dual
# Remove old configuration file
rm -f "$BIRD_CONFIG"
get log_file $section
get log $section
get debug $section
get router_id $section
get table $section
get listen_bgp_addr $section
get listen_bgp_port $section
get listen_bgp_dual $section
# First line of the NEW configuration file
echo "#Bird6 configuration using UCI:" > $BIRD_CONFIG
writeToConfig " "
[ -n "$log_file" -a -n "$log" ] && writeToConfig 'log "'$log_file'" '$log';'
write "debug protocols $debug;" $debug
writeToConfig " "
writeToConfig "#Router ID"
write "router id $router_id;" $router_id
writeToConfig " "
writeToConfig "#Secondary tables"
config_foreach prepare_tables 'table'
if [ -n "$listen_bgp_dual" -o "$listen_bgp_dual" = "0" ]; then
writeToConfig "listen bgp $listen_bgp_addr $listen_bgp_port v6only;"
else
writeToConfig "listen bgp $listen_bgp_addr $listen_bgp_port dual;"
fi
writeToConfig " "
}
# Function: prepare_routes $1
# $1 string
# This function gets each "route" section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI route section. Each type of route has its own treatment.
prepare_routes() {
local instance; local prefix; local via; local type
local section="$1"
local protoInstance="$2"
get instance $section
if [ "$instance" = "$protoInstance" ]; then
get type $section
case "$type" in
"router")
get prefix $section
get via $section
[ -n "$prefix" -a -n "$via" ] && writeToConfig " route $prefix via $via;"
;;
"special")
get prefix $section
get attribute $section
[ -n "$prefix" -a -n "$attribute" ] && writeToConfig " route $prefix $attribute;"
;;
"iface")
get prefix $section
get iface $section
[ -n "$prefix" -a -n "$iface" ] && writeToConfig ' route '$prefix' via "'$iface'";'
;;
"multipath")
get prefix $section
write " route $prefix multipath" $prefix
config_list_foreach $section l_via multipath_list
writeToConfig " ;"
;;
esac
fi
}
# Function: prepare_kernel $1
# $1 string
# This function gets each "kernel" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI kernel section.
prepare_kernel() {
local section="$1"
write "#$section configuration:" $section
local disabled; local table; local kernel_table; local import; local export; local scan_time; local persist; local learn
get_bool disabled $section
get table $section
get import $section
get export $section
get scan_time $section
get kernel_table $section
get learn $section
get persist $section
writeToConfig "protocol kernel {"
write_bool disabled $disabled
write " table $table;" $table
write " kernel table $kernel_table;" $kernel_table
write_bool learn $learn
write_bool persist $persist
write " scan time $scan_time;" $scan_time
write " import $import;" $import
write " export $export;" $export
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_static $1
# $1 string
# This function gets each "static" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI static section.
prepare_static() {
local section="$1"
local disabled
get disabled $section
if [ "$disabled" -eq 0 ]; then
local table
get table $section
writeToConfig "#$section configration:" $section
writeToConfig "protocol static {"
write " table $table;" $table
config_foreach prepare_routes 'route' $section
writeToConfig "}"
writeToConfig " "
fi
}
# Function: prepare_device $1
# $1 string
# This function gets each "device" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI device section.
prepare_device() {
local section="$1"
local disabled; local scan_time
get disabled $section
get scan_time $section
write "#$section configuration:" $section
writeToConfig "protocol device {"
write_bool disabled $disabled
write " scan time $scan_time;" $scan_time
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp_template $1
# $1 string
# This function gets each "bgp_template" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI bgp_template section.
# Careful! Template options will be replaced by "instance" options if there is any match.
prepare_bgp_template() {
local section="$1"
local disabled; local table; local import; local export; local local_address; local local_as; local neighbor_address; local neighbor_as; local source_address; local next_hop_self; local next_hop_keep; local rr_client; local rr_cluster_id; local import_limit; local import_limit_action; local export_limit; local export_limit_action; local receive_limit; local receive_limit_action
get_bool disabled $section
get_bool next_hop_self $section
get_bool next_hop_keep $section
get table $section
get import $section
get export $section
get local_address $section
get local_as $section
get rr_client $section
get rr_cluster_id $section
get import_limit $section
get import_limit_action $section
get export_limit $section
get export_limit_action $section
get receive_limit $section
get receive_limit_action $section
get neighbor_address $section
get neighbor_as $section
writeToConfig "#$section template:"
writeToConfig "template bgp $section {"
[ -n "$disabled" ] && write_bool disabled $disabled
write " table $table;" $table
write " local as $local_as;" $local_as
write " source address $local_address;" $local_address
write " import $import;" $import
write " export $export;" $export
if [ -n "$next_hop_self" ]; then
[ "$next_hop_self" = "1" ] && writeToConfig " next hop self;" || writeToConfig "# next hop self;"
fi
if [ -n "$next_hop_keep" ]; then
[ "$next_hop_keep" = "1" ] && writeToConfig " next hop keep;" || writeToConfig "# next hop keep;"
fi
[ "$rr_client" = "1" ] && writeToConfig " rr client;" || writeToConfig "# rr client;"
write " rr cluster id $rr_cluster_id;" $rr_cluster_id
if [ -n "$import_limit" -a "$import_limit" > "0" ]; then
[ -z "$import_limit_action" ] && $import_limit_action = "warn"
writeToConfig " import limit $import_limit action $import_limit_action;"
fi
if [ -n "$export_limit" -a "$export_limit" > "0" ]; then
[ -z "$export_limit_action" ] && $export_limit_action = "warn"
writeToConfig " export limit $export_limit action $export_limit_action;"
fi
if [ -n "$receive_limit" -a "$receive_limit" > "0" ]; then
[ -z "$receive_limit_action" ] && $receive_limit_action = "warn"
writeToConfig " receive limit $receive_limit action $receive_limit_action;"
fi
[ -n "$neighbor_address" -a -n "$neighbor_as" ] && writeToConfig " neighbor $neighbor_address as $neighbor_as;"
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp $1
# $1 string
# This function gets each "bgp" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI bgp section.
# Careful! The options set in bgp instances overlap bgp_template ones.
prepare_bgp() {
local section="$1"
local disabled; local table; local template; local description; local import; local export; local local_address; local local_as; local neighbor_address; local neighbor_as; local rr_client; local rr_cluster_id; local import_limit; local import_limit_action; local export_limit; local export_limit_action; local receive_limit; local receive_limit_action
get disabled $section
get table $section
get template $section
get description $section
get import $section
get export $section
get local_address $section
get local_as $section
get rr_client $section
get rr_cluster_id $section
get import_limit $section
get import_limit_action $section
get export_limit $section
get export_limit_action $section
get receive_limit $section
get receive_limit_action $section
get neighbor_address $section
get neighbor_as $section
writeToConfig "#$section configuration:"
[ -n "$template" ] && writeToConfig "protocol bgp $section from $template {" || writeToConfig "protocol bgp $section {"
[ -n "$disabled" ] && write_bool disabled $disabled
write " table $table;" $table
# [ -n "$description" ] && writeToConfig ' description "'$description'";'
write " local as $local_as;" $local_as
write " source address $local_address;" $local_address
write " import $import;" $import
write " export $export;" $export
if [ -n "$next_hop_self" ]; then
[ "$next_hop_self" = "1" ] && writeToConfig " next hop self;" || writeToConfig "# next hop self;"
fi
if [ -n "$next_hop_keep" ]; then
[ "$next_hop_keep" = "1" ] && writeToConfig " next hop keep;" || writeToConfig "# next hop keep;"
fi
[ "$rr_client" = "1" ] && writeToConfig " rr client;" || writeToConfig "# rr client;"
write " rr cluster id $rr_cluster_id;" $rr_cluster_id
if [ -n "$import_limit" -a "$import_limit" > "0" ]; then
[ -z "$import_limit_action" ] && $import_limit_action = "warn"
writeToConfig " import limit $import_limit action $import_limit_action;"
fi
if [ -n "$export_limit" -a "$export_limit" > "0" ]; then
[ -z "$export_limit_action" ] && $export_limit_action = "warn"
writeToConfig " export limit $export_limit action $export_limit_action;"
fi
if [ -n "$receive_limit" -a "$receive_limit" > "0" ]; then
[ -z "$receive_limit_action" ] && $receive_limit_action = "warn"
writeToConfig " receive limit $receive_limit action $receive_limit_action;"
fi
[ -n "$neighbor_address" -a -n "$neighbor_as" ] && writeToConfig " neighbor $neighbor_address as $neighbor_as;"
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp_filters $1
# $1 string
# This function gets each "bgp_filter" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI bgp_filter section.
# This function checks if the filter file exists and, in that case, it writes its content to the configuration file.
prepare_bgp_filters() {
local section="$1"
local type
local file_path
get type $section
get file_path $section
if [ -e "$file_path" ]; then
local filter_content=`cat $file_path`
if [ -n "$type" -a "$type" = "bgp" ]; then
writeToConfig "#Filter $section:"
writeToConfig "${filter_content}"
writeToConfig " "
fi
fi
}
BIRD_BIN="/usr/sbin/${BIRD}"
# Special non-terminal-rich output for Luci calls
LUCI="false"
. /etc/${BIRD}/init.d/${BIRD}-lib.sh
start() {
config_load bird6
config_load ${BIRD}
local use_UCI_config
get use_UCI_config 'bird'
if [ -z "$use_UCI_config" -o "$use_UCI_config" = "0" ]; then
service_start $BIRD_BIN -d -c $BIRD_CONFIG -P $SERVICE_PID_FILE
#Start the service
if [ "${LUCI}" == "false" ]; then
echo "Starting ${BIRD} Service [ ... ]"
fi
if [ -f ${BIRD_ERR} ]; then
echo "" > ${BIRD_ERR}
else
touch ${BIRD_ERR}
fi
if [ -z "${use_UCI_config}" -o "${use_UCI_config}" = "0" ]; then
# Disable Custom bird-openwrt settings.
# Use default behaviour and files
${BIRD_BIN} -d -c ${BIRD_CONFIG} -P ${SERVICE_PID_FILE} -D ${BIRD_LOG} &> ${BIRD_ERR} &
else
#Set Bird6 configuration location:
local UCI_config_File
get UCI_config_File 'bird'
BIRD_CONFIG=${UCI_config_File:-/tmp/bird6.conf}
local UCI_config_file
local log_file
get UCI_config_file 'bird'
get log_file 'global'
BIRD_CONFIG="${UCI_config_file:-$BIRD_CONFIG}"
BIRD_LOG="${log_file:-$BIRD_LOG}"
#Backup previous configuration
[ -f ${BIRD_CONFIG} ] && cp ${BIRD_CONFIG} ${BIRD_CONFIG}.bak
#Setup the basic configuration
prepare_global 'global'
# Gather and set all Functions
gather_functions
# Gather and set all Filters
gather_filters
# Setup Main Protocols
config_foreach prepare_kernel 'kernel'
config_foreach prepare_static 'static'
config_foreach prepare_device 'device'
#config_foreach prepare_direct 'direct'
#Setup the protocols configuration (currently BGP only)
config_foreach prepare_direct 'direct'
config_foreach prepare_pipe 'pipe'
#Setup protocol's configuration: BGP
config_foreach prepare_bgp_template 'bgp_template'
config_foreach prepare_bgp 'bgp'
config_foreach prepare_bgp_filters 'filter'
#Setup protocol's configuration: OSPF
#config_foreach prepare_ospf_instance 'ospf'
#Start the service
service_start $BIRD_BIN -d -c $BIRD_CONFIG -P $SERVICE_PID_FILE
${BIRD_BIN} -d -c ${BIRD_CONFIG} -P ${SERVICE_PID_FILE} -D ${BIRD_LOG} &>${BIRD_ERR} &
fi
while [ ! -s ${SERVICE_PID_FILE} ]; do
sleep 1
if [ -s ${BIRD_ERR} ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Start Status: \033[0;31m[ FAILED ]\e[m"
cat ${BIRD_ERR}
cat ${BIRD_ERR} >> ${BIRD_LOG}
else
echo "${BIRD} - Failed: $(cat ${BIRD_ERR})"
cat ${BIRD_ERR} >> ${BIRD_LOG}
fi
break
fi
done
if [ -s ${SERVICE_PID_FILE} ]; then
if [ -s ${BIRD_ERR} ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon already started. Status \033[0;32m[ RUNNING ]\e[m"
else
echo "${BIRD} already started"
fi
else
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Start Status: \033[0;32m[ STARTED ]\e[m"
else
echo "${BIRD} - Started"
fi
fi
# PID File found (service started correctly)
return 0
fi
# PID File not found (error while starting service)
return 1
}
stop() {
service_stop $BIRD_BIN
if [ -s ${SERVICE_PID_FILE} ]; then
config_load ${BIRD}
local log_file
get log_file 'global'
BIRD_LOG="${log_file:-$BIRD_LOG}"
start-stop-daemon -p ${SERVICE_PID_FILE} -K 2>&1 >> ${BIRD_LOG}
if [ $? -eq 0 ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Stop Status: \033[0;32m[ OK ]\e[m"
else
echo "${BIRD} - Stopped"
fi
else
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Stop Status: \033[0;31m[ FAILED ]\e[m"
echo "Check ${BIRD_LOG} file for more information."
else
echo "${BIRD} Failed to Stop. See Log file: ${BIRD_LOG}"
fi
fi
else
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} Daemon Service already stopped. \033[0;31m[ FAILED ]\e[m"
else
echo "${BIRD} already stopped"
fi
fi
return 0
}
restart() {
stop
sleep 1
if [ "${LUCI}" == "true" ]; then
echo " ... "
fi
start
}
reload() {
service_reload $BIRD_BIN
service_reload ${BIRD_BIN}
}
status() {
if [ -s ${SERVICE_PID_FILE} ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} start status: \033[0;32m[ RUNNING ]\e[m"
else
echo "${BIRD}: Running"
fi
return 0
else
if [ -s ${BIRD_ERR} ]; then
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} service status: \033[0;31m[ STOPPED ]\e[m"
cat ${BIRD_ERR}
else
echo "${BIRD}: Failed - $(cat ${BIRD_ERR})"
fi
return 2
else
if [ "${LUCI}" == "false" ]; then
echo -e "${BIRD} service status: \033[0;31m[ STOPPED ]\e[m"
else
echo "${BIRD}: Stopped"
fi
return 1
fi
fi
}
# Luci-specific calls (stripped output).
# The following scripts are not meant to be ran using Ash Terminal
# Used in: LUCI/model/cbi/bird6/status.lua
start_quiet() {
LUCI="true"
start
}
stop_quiet() {
LUCI="true"
stop
}
restart_quiet() {
LUCI="true"
restart
}
status_quiet() {
LUCI="true"
status
}

View File

@ -0,0 +1,473 @@
# Bird6-OpenWRT Library - Functions used in /etc/init.d/bird6 script.
#
#
# Copyright (C) 2014-2017 - Eloi Carbo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Function: writeToConfig $1
# $1 string.
# Allows to write in the $BIRD_CONFIG file, the string $1. This function does not check the $1 string.
# Example: writeToConfig "value: $N"
writeToConfig() {
echo "$1" >> ${BIRD_CONFIG}
}
# Function: write $1 $2
# $1 string. $2 string.
# This function checks if $2 is empty. If not, it writes the string $1 in the $BIRD_CONFIG file.
# Use write function to check if $1, value found inside $2, is not empty and can be written in the configuration file.
# Example: N=""; write "value: $N" $N;
write() {
[ -n "$2" ] && writeToConfig "$1"
}
#Function: write_bool $1 $2
# $1 string; $2 boolean
# This function checks if $2 is true or false and write the $1 string into $BIRD_CONFIG file.
# The function writes a # before the $2 string if its false.
# Example: local N=0; write_bool $N
write_bool() {
[ "$2" == 0 ] && writeToConfig "# $1;" || writeToConfig " $1;"
}
# Function: get $1 $2
# $1 string. $2 string
# This function uses the external UCI function "config_get $result $section $option" to obtain a string value from UCI config file.
# To use this function, use the same name of the UCI option for the variable.
# Example: UCI (option id 'abcd'); local id; get id $section
get() {
config_get $1 $2 $1
}
# Function: get_bool $1 $2
# $1 boolean. $2 string
# This function uses the external UCI function "config_get_bool $result $section $option" to obtain a boolean value from UCI config file.
# To use this function, use the same name of the UCI option for the variable $1.
# Example: UCI (option use_ipv6 '1'); local use_ipv6; get use_ipv6 $section
get_bool() {
config_get_bool $1 $2 $1
}
# Function: multipath_list $1
# $1 string
# This function writes the $1 string in the multipath routes.
multipath_list() {
write " via $1" $1
}
# Function: prepare_tables $1
# $1 string
# This function gets each "table" section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI table section
prepare_tables() {
local section="$1"; local name
get name ${section}
write "table ${name};" ${name}
}
# Function: prepare_global $1
# $1 string
# This function gets each "global" section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI global section. prepare_global is the first configuration set in the bird6.conf and removes the old file.
prepare_global () {
local section="$1"
local log_file; local log; local debug; local router_id; local table
local listen_bgp_addr; local listen_bgp_port; local listen_bgp_dual
# Remove old configuration file
rm -f "${BIRD_CONFIG}"
get log_file ${section}
get log ${section}
get debug ${section}
get router_id ${section}
get table ${section}
get listen_bgp_addr ${section}
get listen_bgp_port ${section}
get listen_bgp_dual ${section}
# First line of the NEW configuration file
echo "#Bird6 configuration using UCI:" > ${BIRD_CONFIG}
writeToConfig " "
#TODO: Set Syslog as receiver if empty
# LOGF="${log_file:-syslog]}"
#TODO: If $log/$debug are empty, set to off
if [ -n "${log_file}" -a -n "${log}" ]; then
firstEntry="${log:0:3}"
if [ "${firstEntry}" = "all" -o "${firstEntry}" = "off" ]; then
writeToConfig 'log "'${log_file}'" '${firstEntry}';'
else
logEntries=$(echo ${log} | tr " " ",")
writeToConfig "log \"${log_file}\" { ${logEntries} };"
fi
fi
if [ -n "${debug}" ]; then
firstEntry="${debug:0:3}"
if [ "${firstEntry}" = "all" -o "${firstEntry}" = "off" ]; then
writeToConfig "debug protocols ${firstEntry};"
else
debugEntries=$(echo ${debug} | tr " " ",")
writeToConfig "debug protocols { ${debugEntries} };"
fi
fi
writeToConfig " "
writeToConfig "#Router ID"
write "router id ${router_id};" ${router_id}
writeToConfig " "
writeToConfig "#Secondary tables"
config_foreach prepare_tables 'table'
if [ -n "${listen_bgp_dual}" -o "${listen_bgp_dual}" = "0" ]; then
writeToConfig "listen bgp ${listen_bgp_addr} ${listen_bgp_port} v6only;"
else
writeToConfig "listen bgp ${listen_bgp_addr} ${listen_bgp_port} dual;"
fi
writeToConfig " "
}
# Function: prepare_routes $1
# $1 string
# This function gets each "route" section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI route section. Each type of route has its own treatment.
prepare_routes() {
local instance; local prefix; local via; local type
local section="$1"
local protoInstance="$2"
get instance ${section}
get type ${section}
get prefix ${section}
if [ "${instance}" = "${protoInstance}" ]; then
case "${type}" in
"router")
get via ${section}
[ -n "${prefix}" -a -n "${via}" ] && writeToConfig " route ${prefix} via ${via};"
;;
"special")
get attribute ${section}
[ -n "${prefix}" -a -n "${attribute}" ] && writeToConfig " route ${prefix} ${attribute};"
;;
"iface")
get iface ${section}
[ -n "${prefix}" -a -n "${iface}" ] && writeToConfig ' route '${prefix}' via "'${iface}'";'
;;
"multipath")
write " route ${prefix} multipath" ${prefix}
config_list_foreach ${section} l_via multipath_list
writeToConfig " ;"
;;
esac
fi
}
# Function: prepare_kernel $1
# $1 string
# This function gets each "kernel" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI kernel section.
prepare_kernel() {
local section="$1"
local disabled; local table; local kernel_table; local import; local export
local scan_time; local persist; local learn
get_bool disabled ${section}
get table ${section}
get import ${section}
get export ${section}
get scan_time ${section}
get kernel_table ${section}
get learn ${section}
get persist ${section}
write "#${section} configuration:" ${section}
writeToConfig "protocol kernel ${section} {" ${section}
write_bool disabled ${disabled}
write " table ${table};" ${table}
write " kernel table ${kernel_table};" ${kernel_table}
write_bool learn ${learn}
write_bool persist ${persist}
write " scan time ${scan_time};" ${scan_time}
write " import ${import};" ${import}
write " export ${export};" ${export}
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_static $1
# $1 string
# This function gets each "static" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI static section.
prepare_static() {
local section="$1"
local disabled; local table
get disabled ${section}
get table ${section}
if [ "${disabled}" -eq 0 ]; then
writeToConfig "#${section} configration:" ${section}
writeToConfig "protocol static {"
write " table ${table};" ${table}
config_foreach prepare_routes 'route' ${section}
writeToConfig "}"
writeToConfig " "
fi
}
# Function: prepare_direct $1
# $1 string
# This function gets each "direct" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI direct section.
prepare_direct() {
local section="$1"
local disabled; local interface
get disabled ${section}
get interface ${section}
write "#${section} configuration:" ${section}
writeToConfig "protocol direct {"
write_bool disabled ${disabled}
write " interface ${interface};" ${interface}
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_pipe $1
# $1 string
# This function gets each "pipe" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI direct section.
prepare_pipe() {
local section="$1"
local disabled; local table; local peer_table; local mode; local import; local export
get disabled ${section}
get peer_table ${section}
get mode ${section}
get table ${section}
get import ${section}
get export ${section}
write "#${section} configuration:" ${section}
writeToConfig "protocol pipe ${section} {" ${section}
write_bool disabled ${disabled}
write " table ${table};" ${table}
write " peer table ${peer_table};" ${peer_table}
write " mode ${mode};" ${mode}
write " import ${import};" ${import}
write " export ${export};" ${export}
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_device $1
# $1 string
# This function gets each "device" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI device section.
prepare_device() {
local section="$1"
local disabled; local scan_time
get disabled ${section}
get scan_time ${section}
write "#${section} configuration:" ${section}
writeToConfig "protocol device {"
write_bool disabled ${disabled}
write " scan time ${scan_time};" ${scan_time}
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp_template $1
# $1 string
# This function gets each "bgp_template" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI bgp_template section.
# Careful! Template options will be replaced by "instance" options if there is any match.
prepare_bgp_template() {
local section="$1"
local disabled; local table; local import; local export; local local_address
local local_as; local neighbor_address; local neighbor_as; local source_address
local next_hop_self; local next_hop_keep; local rr_client; local rr_cluster_id
local import_limit; local import_limit_action; local export_limit; local export_limit_action
local receive_limit; local receive_limit_action; local igp_table
get_bool disabled ${section}
get_bool next_hop_self ${section}
get_bool next_hop_keep ${section}
get table ${section}
get import ${section}
get export ${section}
get local_address ${section}
get local_as ${section}
get igp_table ${section}
get rr_client ${section}
get rr_cluster_id ${section}
get import_limit ${section}
get import_limit_action ${section}
get export_limit ${section}
get export_limit_action ${section}
get receive_limit ${section}
get receive_limit_action ${section}
get neighbor_address ${section}
get neighbor_as ${section}
writeToConfig "#${section} template:"
writeToConfig "template bgp ${section} {"
[ -n "${disabled}" ] && write_bool disabled ${disabled}
write " table ${table};" ${table}
write " local as ${local_as};" ${local_as}
write " source address ${local_address};" ${local_address}
write " import ${import};" ${import}
write " export ${export};" ${export}
if [ -n "${next_hop_self}" ]; then
[ "${next_hop_self}" = "1" ] && writeToConfig " next hop self;" || writeToConfig "# next hop self;"
fi
if [ -n "${next_hop_keep}" ]; then
[ "${next_hop_keep}" = "1" ] && writeToConfig " next hop keep;" || writeToConfig "# next hop keep;"
fi
[ -n "${igp_table}" ] && writeToConfig " igp table ${igp_table};"
[ "${rr_client}" = "1" ] && writeToConfig " rr client;" || writeToConfig "# rr client;"
write " rr cluster id ${rr_cluster_id};" ${rr_cluster_id}
if [ -n "${import_limit}" -a "${import_limit}" > "0" ]; then
[ -z "${import_limit_action}" ] && ${import_limit_action} = "warn"
writeToConfig " import limit ${import_limit} action ${import_limit_action};"
fi
if [ -n "${export_limit}" -a "${export_limit}" > "0" ]; then
[ -z "${export_limit_action}" ] && ${export_limit_action} = "warn"
writeToConfig " export limit ${export_limit} action ${export_limit_action};"
fi
if [ -n "${receive_limit}" -a "${receive_limit}" > "0" ]; then
[ -z "${receive_limit_action}" ] && ${receive_limit_action} = "warn"
writeToConfig " receive limit ${receive_limit} action ${receive_limit_action};"
fi
[ -n "${neighbor_address}" -a -n "${neighbor_as}" ] && writeToConfig " neighbor ${neighbor_address} as ${neighbor_as};"
writeToConfig "}"
writeToConfig " "
}
# Function: prepare_bgp $1
# $1 string
# This function gets each "bgp" protocol section in the UCI configuration and sets each option in the bird6.conf file.
# $1 is set as the ID of the current UCI bgp section.
# Careful! The options set in bgp instances overlap bgp_template ones.
prepare_bgp() {
local section="$1"
local disabled; local table; local template; local description; local import
local export; local local_address; local local_as; local neighbor_address
local neighbor_as; local rr_client; local rr_cluster_id; local import_limit
local import_limit_action; local export_limit; local export_limit_action
local receive_limit; local receive_limit_action; local igp_table
get disabled ${section}
get table ${section}
get template ${section}
get description ${section}
get import ${section}
get export ${section}
get local_address ${section}
get local_as ${section}
get igp_table ${section}
get rr_client ${section}
get rr_cluster_id ${section}
get import_limit ${section}
get import_limit_action ${section}
get export_limit ${section}
get export_limit_action ${section}
get receive_limit ${section}
get receive_limit_action ${section}
get neighbor_address ${section}
get neighbor_as ${section}
writeToConfig "#${section} configuration:"
[ -n "${template}" ] && writeToConfig "protocol bgp ${section} from ${template} {" || writeToConfig "protocol bgp ${section} {"
[ -n "${disabled}" ] && write_bool disabled ${disabled}
write " table ${table};" ${table}
write " local as ${local_as};" ${local_as}
write " source address ${local_address};" ${local_address}
write " import ${import};" ${import}
write " export ${export};" ${export}
if [ -n "${next_hop_self}" ]; then
[ "${next_hop_self}" = "1" ] && writeToConfig " next hop self;" || writeToConfig "# next hop self;"
fi
if [ -n "${next_hop_keep}" ]; then
[ "${next_hop_keep}" = "1" ] && writeToConfig " next hop keep;" || writeToConfig "# next hop keep;"
fi
[ -n "${igp_table}" ] && writeToConfig " igp table ${igp_table};"
[ "${rr_client}" = "1" ] && writeToConfig " rr client;" || writeToConfig "# rr client;"
write " rr cluster id ${rr_cluster_id};" ${rr_cluster_id}
if [ -n "${import_limit}" -a "${import_limit}" > "0" ]; then
[ -z "${import_limit_action}" ] && ${import_limit_action} = "warn"
writeToConfig " import limit ${import_limit} action ${import_limit_action};"
fi
if [ -n "${export_limit}" -a "${export_limit}" > "0" ]; then
[ -z "${export_limit_action}" ] && ${export_limit_action} = "warn"
writeToConfig " export limit ${export_limit} action ${export_limit_action};"
fi
if [ -n "${receive_limit}" -a "${receive_limit}" > "0" ]; then
[ -z "${receive_limit_action}" ] && ${receive_limit_action} = "warn"
writeToConfig " receive limit ${receive_limit} action ${receive_limit_action};"
fi
[ -n "${neighbor_address}" -a -n "${neighbor_as}" ] && writeToConfig " neighbor ${neighbor_address} as ${neighbor_as};"
writeToConfig "}"
writeToConfig " "
}
# Function: gather_filters
# This function gets all the FILES under /filters folder and adds
# them into the config as %include elements on top of the file
# If there are no filters, the section will remain empty.
gather_filters() {
writeToConfig "#Filters Section:"
for filter in $(find /etc/${BIRD}/filters -type f); do
writeToConfig "include \"${filter}\";"
done
writeToConfig "#End of Filters --"
writeToConfig " "
}
# Function: gather_functions
# This function gets all the FILES under /functions folder and adds
# them into the config as %include elements on top of the file
# If there are no filters, the section will remain empty.
gather_functions() {
writeToConfig "#Functions Section:"
for func in $(find /etc/${BIRD}/functions -type f); do
writeToConfig "include \"${func}\";"
done
writeToConfig "#End of Functions --"
writeToConfig " "
}

View File

@ -1,6 +1,5 @@
--[[
Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
BGP/Bird integration with OpenWRT and QMP
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -18,45 +17,68 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
require("luci.sys")
local http = require "luci.http"
local uci = require "luci.model.uci"
local uciout = uci.cursor()
local uci = luci.model.uci.cursor()
-- Repeated Strings
local common_string = "Valid options are:<br />" .. "1. all (All the routes)<br />" .. "2. none (No routes)<br />" .. "3. filter <b>Your_Filter_Name</b> (Call a specific filter from any of the available in the filters files)"
local imp_string = "Set if the protocol must import routes.<br />" .. common_string
local exp_string = "Set if the protocol must export routes.<br />" .. common_string
m=Map("bird6", "Bird6 BGP protocol's configuration")
tab_templates = {}
uciout:foreach('bird6', 'bgp_template', function (s)
uci:foreach('bird6', 'bgp_template', function (s)
local name = s[".name"]
if (name ~= nil) then
table.insert(tab_templates, name)
end
end)
-- Section BGP Templates
--
-- BGP TEMPLATES
--
sect_templates = m:section(TypedSection, "bgp_template", "BGP Templates", "Configuration of the templates used in BGP instances.")
sect_templates.addremove = true
sect_templates.anonymous = false
disabled = sect_templates:option(Flag, "disabled", "Disabled", "Enable/Disable BGP Protocol")
disabled.optional=true
description = sect_templates:option(TextValue, "description", "Description", "Description of the current BGP instance")
description.optional = true
table = sect_templates:option(ListValue, "table", "Table", "Set the table used for BGP Routing")
table.optional=true
uciout:foreach("bird6", "table",
uci:foreach("bird6", "table",
function (s)
table:value(s.name)
end)
table:value("")
table.default = ""
import = sect_templates:option(Value, "import", "Import","")
igp_table = sect_templates:option(ListValue, "igp_table", "IGP Table", "Select the IGP Routing Table to use. Hint: usually the same table as BGP.")
igp_table.optional = true
uci:foreach("bird6", "table",
function(s)
igp_table:value(s.name)
end)
igp_table:value("")
igp_table.default = ""
import = sect_templates:option(Value, "import", "Import", imp_string)
import.optional=true
export = sect_templates:option(Value, "export", "Export", "")
export = sect_templates:option(Value, "export", "Export", exp_string)
export.optional=true
source_addr = sect_templates:option(Value, "source_address", "Source Address", "Source address for BGP routing. By default uses Router ID")
source_addr.optional = true
description = sect_templates:option(TextValue, "description", "Description", "Description of the current BGP instance")
description.optional = true
local_address = sect_templates:option(Value, "local_address", "Local BGP address", "")
local_address.optional = false
local_as = sect_templates:option(Value, "local_as", "Local AS", "")
local_as.optional = false
next_hop_self = sect_templates:option(Flag, "next_hop_self", "Next hop self", "Avoid next hop calculation and advertise own source address as next hop")
next_hop_self.default = nil
@ -73,90 +95,121 @@ rr_client.optional = true
rr_cluster_id = sect_templates:option(Value, "rr_cluster_id", "Route Reflector Cluster ID", "Identificator of the RR cluster. By default uses the Router ID")
rr_cluster_id.optional = true
import_limit = sect_templates:option(Value, "import_limit", "Routes import limit", "Specify an import route limit. By default is disabled '0'")
import_limit.default= "0"
import_limit.optional = true
import_trigger = sect_templates:option(Flag, "import_trigger", "Import Limit", "Enable Routes Import limit settings")
import_trigger.default = 0
import_trigger.rmempty = false
import_trigger.optional = false
import_limit = sect_templates:option(Value, "import_limit", "Routes import limit", "Specify an import route limit.")
import_limit:depends({import_trigger = "1"})
import_limit.rmempty = true
import_limit_action = sect_templates:option(ListValue, "import_limit_action", "Routes import limit action", "Action to take when import routes limit ir reached")
import_limit_action:depends({import_trigger = "1"})
import_limit_action:value("warn")
import_limit_action:value("block")
import_limit_action:value("disable")
import_limit_action:value("restart")
import_limit_action.default = "warn"
import_limit_action.optional = true
import_limit_action.rmempty = true
export_limit = sect_templates:option(Value, "export_limit", "Routes export limit", "Specify an export route limit. By default is disabled '0'")
export_limit.default="0"
export_limit.optional = true
export_trigger = sect_templates:option(Flag, "export_trigger", "Export Limit", "Enable Routes Export limit settings")
export_trigger.default = 0
export_trigger.rmempty = false
export_trigger.optional = false
export_limit = sect_templates:option(Value, "export_limit", "Routes export limit", "Specify an export route limit.")
export_limit:depends({export_trigger = "1"})
export_limit.rmempty = true
export_limit_action = sect_templates:option(ListValue, "export_limit_action", "Routes export limit action", "Action to take when export routes limit is reached")
export_limit_action:depends({export_trigger = "1"})
export_limit_action.rmempty = true
export_limit_action:value("warn")
export_limit_action:value("block")
export_limit_action:value("disable")
export_limit_action:value("restart")
export_limit_action.default = "warn"
export_limit_action.optional = true
receive_limit = sect_templates:option(Value, "receive_limit", "Routes received limit", "Specify a received route limit. By default is disabled '0'")
receive_limit.default="0"
receive_limit.optional = true
receive_trigger = sect_templates:option(Flag, "receive_trigger", "Received Limit", "Enable Routes Received Limit settings")
receive_trigger.default = 0
receive_trigger.rmempty = false
receive_trigger.optional = false
receive_limit = sect_templates:option(Value, "receive_limit", "Routes received limit", "Specify a received route limit.")
receive_limit:depends({receive_trigger = "1"})
receive_limit.rmempty = true
receive_limit_action = sect_templates:option(ListValue, "receive_limit_action", "Routes received limit action", "Action to take when received routes limit is reached")
receive_limit_action:depends({receive_trigger = "1"})
receive_limit_action:value("warn")
receive_limit_action:value("block")
receive_limit_action:value("disable")
receive_limit_action:value("restart")
receive_limit_action.default = "warn"
receive_limit_action.optional = true
local_address = sect_templates:option(Value, "local_address", "Local BGP address", "")
local_address.optional=true
local_as = sect_templates:option(Value, "local_as", "Local AS", "")
local_as.optional=true
-- Section BGP Instances:
receive_limit_action.rmempty= true
--
-- BGP INSTANCES
--
sect_instances = m:section(TypedSection, "bgp", "BGP Instances", "Configuration of the BGP protocol instances")
sect_instances.addremove = true
sect_instances.anonymous = false
templates = sect_instances:option(ListValue, "template", "Templates", "Available BGP templates")
uciout:foreach("bird6", "bgp_template",
uci:foreach("bird6", "bgp_template",
function(s)
templates:value(s[".name"])
end)
templates:value("")
neighbor_address = sect_instances:option(Value, "neighbor_address", "Neighbor IP Address", "")
neighbor_as = sect_instances:option(Value, "neighbor_as", "Neighbor AS", "")
disabled = sect_instances:option(Flag, "disabled", "Disabled", "Enable/Disable BGP Protocol")
disabled.optional=true
disabled.default=nil
table = sect_instances:option(ListValue, "table", "Table", "Set the table used for BGP Routing")
table.optional=true
uciout:foreach("bird6", "table",
function (s)
table:value(s.name)
end)
table:value("")
disabled.optional = false
disabled.rmempty = false
disabled.default = nil
description = sect_instances:option(TextValue, "description", "Description", "Description of the current BGP instance")
description.optional = true
import = sect_instances:option(Value, "import", "Import","")
table = sect_instances:option(ListValue, "table", "Table", "Set the table used for BGP Routing")
table.optional=true
uci:foreach("bird6", "table",
function (s)
table:value(s.name)
end)
table:value("")
table.default = ""
igp_table = sect_instances:option(ListValue, "igp_table", "IGP Table", "Select the IGP Routing Table to use. Hint: usually the same table as BGP.")
igp_table.optional = true
uci:foreach("bird6", "table",
function(s)
igp_table:value(s.name)
end)
igp_table:value("")
igp_table.default = ""
import = sect_instances:option(Value, "import", "Import", imp_string)
import.optional=true
export = sect_instances:option(Value, "export", "Export", "")
export = sect_instances:option(Value, "export", "Export", exp_string)
export.optional=true
source_addr = sect_instances:option(Value, "source_address", "Source Address", "Source address for BGP routing. By default uses Router ID")
source_addr.optional = true
source_address = sect_instances:option(Value, "source_address", "Source Address", "Source address for BGP routing. By default uses Router ID")
source_address.optional = true
local_address = sect_instances:option(Value, "local_address", "Local BGP address", "")
local_address.optional=true
local_as = sect_instances:option(Value, "local_as", "Local AS", "")
local_as.optional=true
neighbor_address = sect_instances:option(Value, "neighbor_address", "Neighbor IP Address", "")
neighbor_address.optional = false
neighbor_as = sect_instances:option(Value, "neighbor_as", "Neighbor AS", "")
neighbor_as.optional = false
next_hop_self = sect_instances:option(Flag, "next_hop_self", "Next hop self", "Avoid next hop calculation and advertise own source address as next hop")
next_hop_self.default = nil
next_hop_self.optional = true
@ -172,66 +225,62 @@ rr_client.optional = true
rr_cluster_id = sect_instances:option(Value, "rr_cluster_id", "Route Reflector Cluster ID", "Identificator of the RR cluster. By default uses the Router ID")
rr_cluster_id.optional = true
import_limit = sect_instances:option(Value, "import_limit", "Routes import limit", "Specify an import route limit. By default is disabled '0'")
import_limit.default="0"
import_limit.optional = true
import_trigger = sect_instances:option(Flag, "import_trigger", "Import Limit", "Enable Routes Import limit settings")
import_trigger.default = 0
import_trigger.rmempty = false
import_trigger.optional = false
import_limit = sect_instances:option(Value, "import_limit", "Routes import limit", "Specify an import route limit.")
import_limit:depends({import_trigger = "1"})
import_limit.rmempty = true
import_limit_action = sect_instances:option(ListValue, "import_limit_action", "Routes import limit action", "Action to take when import routes limit ir reached")
import_limit_action:depends({import_trigger = "1"})
import_limit_action:value("warn")
import_limit_action:value("block")
import_limit_action:value("disable")
import_limit_action:value("restart")
import_limit_action.default = "warn"
import_limit_action.optional = true
import_limit_action.rmempty = true
export_limit = sect_instances:option(Value, "export_limit", "Routes export limit", "Specify an export route limit. By default is disabled '0'")
export_limit.default="0"
export_limit.optional = true
export_trigger = sect_instances:option(Flag, "export_trigger", "Export Limit", "Enable Routes Export limit settings")
export_trigger.default = 0
export_trigger.rmempty = false
export_trigger.optional = false
export_limit = sect_instances:option(Value, "export_limit", "Routes export limit", "Specify an export route limit.")
export_limit:depends({export_trigger = "1"})
export_limit.rmempty = true
export_limit_action = sect_instances:option(ListValue, "export_limit_action", "Routes export limit action", "Action to take when export routes limit is reached")
export_limit_action:depends({export_trigger = "1"})
export_limit_action.rmempty = true
export_limit_action:value("warn")
export_limit_action:value("block")
export_limit_action:value("disable")
export_limit_action:value("restart")
export_limit_action.default = "warn"
export_limit_action.optional = true
receive_limit = sect_instances:option(Value, "receive_limit", "Routes received limit", "Specify a received route limit. By default is disabled '0'")
receive_limit.default="0"
receive_limit.optional = true
receive_trigger = sect_instances:option(Flag, "receive_trigger", "Received Limit", "Enable Routes Received Limit settings")
receive_trigger.default = 0
receive_trigger.rmempty = false
receive_trigger.optional = false
receive_limit = sect_instances:option(Value, "receive_limit", "Routes received limit", "Specify a received route limit.")
receive_limit:depends({receive_trigger = "1"})
receive_limit.rmempty = true
receive_limit_action = sect_instances:option(ListValue, "receive_limit_action", "Routes received limit action", "Action to take when received routes limit is reached")
receive_limit_action:depends({receive_trigger = "1"})
receive_limit_action:value("warn")
receive_limit_action:value("block")
receive_limit_action:value("disable")
receive_limit_action:value("restart")
receive_limit_action.default = "warn"
receive_limit_action.optional = true
-- Section BGP Filters
sect_filters = m:section(TypedSection, "filter", "BGP Filters", "Filters of the BGP instances")
sect_filters.addremove = true
sect_filters.anonymous = false
sect_filters:depends("type", "bgp")
instance = sect_filters:option(ListValue, "instance", "BGP instance", "Filter's BGP instance")
instance:depends("type", "bgp")
uciout:foreach("bird6", "bgp",
function (s)
instance:value(s[".name"])
end)
type = sect_filters:option(Value, "type", "Filter type", "")
type.default = "bgp"
path = sect_filters:option(Value, "file_path", "Filter's file path", "Path to the Filter's file")
path:depends("type", "bgp")
receive_limit_action.rmempty= true
function m.on_commit(self,map)
luci.sys.call('/etc/init.d/bird6 stop; /etc/init.d/bird6 start')
luci.sys.exec('/etc/init.d/bird6 restart')
end
return m

View File

@ -0,0 +1,77 @@
--[[
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]--
local fs = require "nixio.fs"
local filters_dir = "/etc/bird6/filters/"
local lock_file = "/etc/bird6/filter_lock"
m = SimpleForm("bird6", "Bird6 Filters", "<b>INFO:</b> New files are created using Timestamps.<br />In order to make it easier to handle, use SSH to connect to your terminal and rename those files.<br />If your file is not correctly shown in the list, please, refresh your browser.")
s = m:section(SimpleSection)
files = s:option(ListValue, "Files", "Filter Files:")
local new_filter = filters_dir .. os.date("filter-%Y%m%d-%H%M")
-- New File Entry
files:value(new_filter, "New File (".. new_filter .. ")")
files.default = new_filter
local i, file_list = 0, { }
for filename in io.popen("find " .. filters_dir .. " -type f"):lines() do
i = i + 1
files:value(filename, filename)
end
ld = s:option(Button, "_load", "Load File")
ld.inputstyle = "reload"
st_file = s:option(DummyValue, "_stfile", "Editing file:")
function st_file.cfgvalue(self, section)
if ld:formvalue(section) then
fs.writefile(lock_file, files:formvalue(section))
return files:formvalue(section)
else
fs.writefile(lock_file, "")
return ""
end
end
area = s:option(Value, "_filters")
area.template = "bird6/tvalue"
area.rows = 30
function area.cfgvalue(self,section)
if ld:formvalue(section) then
local contents = fs.readfile(files:formvalue(section))
if contents then
return contents
else
return ""
end
else
return ""
end
end
function area.write(self, section)
local locked_file = fs.readfile(lock_file)
if locked_file and not ld:formvalue(section) then
local text = self:formvalue(section):gsub("\r\n?", "\n")
fs.writefile(locked_file, text)
fs.writefile(lock_file, "")
end
end
return m

View File

@ -0,0 +1,77 @@
--[[
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]--
local fs = require "nixio.fs"
local functions_dir = "/etc/bird6/functions/"
local lock_file = "/etc/bird6/function_lock"
m = SimpleForm("bird6", "Bird6 Functions", "<b>INFO:</b> New files are created using Timestamps.<br />In order to make it easier to handle, use SSH to connect to your terminal and rename those files.<br />If your file is not correctly shown in the list, please, refresh your browser.")
s = m:section(SimpleSection)
files = s:option(ListValue, "Files", "Function Files:")
local new_function = functions_dir .. os.date("function-%Y%m%d-%H%M")
-- New File Entry
files:value(new_function, "New File (".. new_function .. ")")
files.default = new_function
local i, file_list = 0, { }
for filename in io.popen("find " .. functions_dir .. " -type f"):lines() do
i = i + 1
files:value(filename, filename)
end
ld = s:option(Button, "_load", "Load File")
ld.inputstyle = "reload"
st_file = s:option(DummyValue, "_stfile", "Editing file:")
function st_file.cfgvalue(self, section)
if ld:formvalue(section) then
fs.writefile(lock_file, files:formvalue(section))
return files:formvalue(section)
else
fs.writefile(lock_file, "")
return ""
end
end
area = s:option(Value, "_functions")
area.template = "bird6/tvalue"
area.rows = 30
function area.cfgvalue(self,section)
if ld:formvalue(section) then
local contents = fs.readfile(files:formvalue(section))
if contents then
return contents
else
return ""
end
else
return ""
end
end
function area.write(self, section)
local locked_file = fs.readfile(lock_file)
if locked_file and not ld:formvalue(section) then
local text = self:formvalue(section):gsub("\r\n?", "\n")
fs.writefile(locked_file, text)
fs.writefile(lock_file, "")
end
end
return m

View File

@ -1,6 +1,5 @@
--[[
Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
BGP/Bird integration with OpenWRT and QMP
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -18,20 +17,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
require("luci.sys")
local http = require "luci.http"
local uci = require "luci.model.uci"
local uciout = uci.cursor()
local uci = luci.model.uci.cursor()
-- Repeated Strings
local common_string = "Valid options are:<br />" .. "1. all (All the routes)<br />" .. "2. none (No routes)<br />" .. "3. filter <b>Your_Filter_Name</b> (Call a specific filter from any of the available in the filters files)"
local imp_string = "Set if the protocol must import routes.<br />" .. common_string
local exp_string = "Set if the protocol must export routes.<br />" .. common_string
m=Map("bird6", "Bird6 general protocol's configuration.")
-- Optional parameters lists
local protoptions = {
{["name"]="table", ["help"]="Auxiliar table for routing", ["depends"]={"static","kernel"}},
{["name"]="import", ["help"]="Set if the protocol must import routes", ["depends"]={"kernel"}},
{["name"]="export", ["help"]="Set if the protocol must export routes", ["depends"]={"kernel"}},
{["name"]="import", ["help"]=imp_string, ["depends"]={"kernel"}},
{["name"]="export", ["help"]=exp_string, ["depends"]={"kernel"}},
{["name"]="scan_time", ["help"]="Time between scans", ["depends"]={"kernel","device"}},
{["name"]="kernel_table", ["help"]="Set which table must be used as auxiliar kernel table", ["depends"]={"kernel"}},
{["name"]="learn", ["help"]="Learn routes", ["depends"]={"kernel"}},
{["name"]="persist", ["help"]="Store routes. After a restart, routes will be still configured", ["depends"]={"kernel"}}
{["name"]="persist", ["help"]="Store routes. After a restart, routes willstill be configured", ["depends"]={"kernel"}}
}
local routeroptions = {
@ -64,11 +67,12 @@ for _,o in ipairs(protoptions) do
value = sect_kernel_protos:option(Flag, o.name, translate(o.name), translate(o.help))
elseif o.name == "table" then
value = sect_kernel_protos:option(ListValue, o.name, translate(o.name), translate(o.help))
uciout:foreach("bird6", "table",
uci:foreach("bird6", "table",
function (s)
value:value(s.name)
end)
value:value("")
value.default = ""
else
value = sect_kernel_protos:option(Value, o.name, translate(o.name), translate(o.help))
end
@ -126,11 +130,12 @@ for _,o in ipairs(protoptions) do
if d == "static" then
if o.name == "table" then
value = sect_static_protos:option(ListValue, o.name, translate(o.name), translate(o.help))
uciout:foreach("bird6", "table",
uci:foreach("bird6", "table",
function (s)
value:value(s.name)
end)
value:value("")
value.default = ""
else
value = sect_static_protos:option(Value, o.name, translate(o.name), translate(o.help))
end
@ -141,11 +146,69 @@ for _,o in ipairs(protoptions) do
end
end
--
-- PIPE PROTOCOL
--
sect_pipe_protos = m:section(TypedSection, "pipe", "Pipe options", "Configuration of the Pipe protocols.")
sect_pipe_protos.addremove = true
sect_pipe_protos.anonymous = false
-- Default Pipe parameters
disabled = sect_pipe_protos:option(Flag, "disabled", "Disabled", "If this option is true, the protocol will not be configured. This protocol will connect the configured 'Table' to the 'Peer Table'.")
disabled.default=0
table = sect_pipe_protos:option(ListValue, "table", "Table", "Select the Primary Table to connect.")
table.optional = false
uci:foreach("bird6", "table",
function (s)
table:value(s.name)
end)
table:value("")
table.default = ""
peer_table = sect_pipe_protos:option(ListValue, "peer_table", "Peer Table", "Select the Secondary Table to connect.")
table.optional = false
uci:foreach("bird6", "table",
function (s)
peer_table:value(s.name)
end)
peer_table:value("")
peer_table.default = ""
mode = sect_pipe_protos:option(ListValue, "mode", "Mode", "Select <b>transparent</b> to retransmit all routes and their attributes<br />Select <b>opaque</b> to retransmit optimal routes (similar to what other protocols do)")
mode.optional = false
mode:value("transparent")
mode:value("opaque")
mode.default = "transparent"
import = sect_pipe_protos:option(Value, "import", "Import",imp_string)
import.optional=true
export = sect_pipe_protos:option(Value, "export", "Export", exp_string)
export.optional=true
--
-- DIRECT PROTOCOL
--
sect_direct_protos = m:section(TypedSection, "direct", "Direct options", "Configuration of the Direct protocols.")
sect_direct_protos.addremove = true
sect_direct_protos.anonymous = false
-- Default Direct parameters
disabled = sect_direct_protos:option(Flag, "disabled", "Disabled", "If this option is true, the protocol will not be configured. This protocol will connect the configured 'Table' to the 'Peer Table'.")
disabled.optional = false
disabled.default = 0
interface = sect_direct_protos:option(Value, "interface", "Interfaces", "By default Direct will generate device routes for all the interfaces. To restrict this behaviour, select a number of patterns to match your desired interfaces:" .. "<br />" .. "1. All the strings <b>MUST</b> be quoted: \"pattern\"" .. "<br />" .. "2. Use * (star) to match patterns: \"eth*\" (<b>include</b> all eth... interfaces)" .. "<br />" .. "3. You can add \"-\" (minus) to exclude patterns: \"-em*\" (<b>exclude</b> all em... interfaces)." .. "<br />" .. "4. Separate several patterns using , (coma): \"-em*\", \"eth*\" (<b>exclude</b> em... and <b>include</b> all eth... interfaces).")
interface.optional = false
interface.default = "\"*\""
--
-- ROUTES FOR STATIC PROTOCOL
--
sect_routes = m:section(TypedSection, "route", "Routes configuration", "Configuration of the routes used in static protocols.")
sect_routes.addremove = true
sect_routes.anonymous = true
@ -153,7 +216,7 @@ sect_routes.anonymous = true
instance = sect_routes:option(ListValue, "instance", "Route instance", "")
i = 0
uciout:foreach("bird6", "static",
uci:foreach("bird6", "static",
function (s)
instance:value(s[".name"])
end)
@ -184,9 +247,11 @@ attribute:depends("type", "special")
iface = sect_routes:option(ListValue, "iface", "Interface", "")
iface:depends("type", "iface")
uciout:foreach("wireless", "wifi-iface",
uci:foreach("network", "interface",
function(section)
iface:value(section[".name"])
if section[".name"] ~= "loopback" then
iface:value(section[".name"])
end
end)
ip = sect_routes:option(Value, "ip", "IP address", "")
@ -194,7 +259,7 @@ ip:depends("type", "ip")
ip.datatype = [[ or"ip4addr", "ip6addr" ]]
function m.on_commit(self,map)
luci.sys.call('/etc/init.d/bird6 stop; /etc/init.d/bird6 start')
luci.sys.exec('/etc/init.d/bird6 restart')
end
return m

View File

@ -1,6 +1,5 @@
--[[
Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
BGP/Bird integration with OpenWRT and QMP
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -30,7 +29,7 @@ s_bird_uci.addremove = False
uuc = s_bird_uci:option(Flag, "use_UCI_config", "Use UCI configuration", "Use UCI configuration instead of the /etc/bird6.conf file")
ucf = s_bird_uci:option(Value, "UCI_config_File", "UCI File", "Specify the file to place the UCI-translated configuration")
ucf = s_bird_uci:option(Value, "UCI_config_file", "UCI File", "Specify the file to place the UCI-translated configuration")
ucf.default = "/tmp/bird6.conf"
-- Named Section: "table"
@ -79,9 +78,8 @@ listen_port.optional = true
listen_dual = s_bird_global:option(Flag, "listen_bgp_dual", "BGP Dual/ipv6", "Set if BGP connections will listen ipv6 only 'ipv6only' or both ipv4/6 'dual' routes")
listen_dual.optional = true
function m.on_commit(self,map)
luci.sys.call('/etc/init.d/bird6 stop; /etc/init.d/bird6 start')
luci.sys.exec('/etc/init.d/bird6 restart')
end
return m

View File

@ -0,0 +1,53 @@
--[[
Copyright (C) 2014-2017 - Eloi Carbo
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]--
local sys = require "luci.sys"
m = SimpleForm("bird6", "Bird6 Daemon Status Page", "This page let you Start, Stop, Restart and check Bird6 Service Status.")
m.reset = false
m.submit = false
s = m:section(SimpleSection)
start = s:option(Button, "_start", "Start Bird4 Daemon:")
start.inputtitle = " Start "
start.inputstyle = "apply"
stop = s:option(Button, "_stop", "Stop Bird4 Daemon:")
stop.inputtitle = " Stop "
stop.inputstyle = "remove"
restart = s:option(Button, "_restart", "Restart Bird4 Daemon:")
restart.inputtitle = "Restart"
restart.inputstyle = "reload"
output = s:option(DummyValue, "_value", "Service Status")
function output.cfgvalue(self, section)
local ret = ""
if start:formvalue(section) then
ret = sys.exec("/etc/init.d/bird6 start_quiet")
elseif stop:formvalue(section) then
ret = sys.exec("/etc/init.d/bird6 stop_quiet")
elseif restart:formvalue(section) then
ret = sys.exec("/etc/init.d/bird6 restart_quiet")
else
ret = sys.exec("/etc/init.d/bird6 status_quiet")
end
return ret
end
return m

View File

@ -0,0 +1,33 @@
#!/bin/sh
# This UCI-Defaults script will MOVE any pre-existing filter
# stored in a file and configured as an UCI item (deprecated)
# The script will try to match any "filter" Section, get its
# "file_path" property and move the file (if exists) to the
# new (v0.3+) default location: /etc/bird{4|6}/filters
[ $# -ne 1 ] && exit 1
BIRD="$1"
. /lib/functions.sh
# This function will move an existing folder configured on
# Bird as a "filter" to filters' folder.
mv_filter() {
local section="$1"
local file_path
config_get file_path ${section} file_path
if [ -f ${file_path} ]; then
mv ${file_path} /etc/${BIRD}/filters/
fi
uci delete ${BIRD}.${section}
}
if [ -f /etc/config/${BIRD} ]; then
config_load ${BIRD}
config_foreach mv_filter 'filter'
uci commit ${BIRD}
fi
exit 0

View File

@ -0,0 +1,13 @@
#!/bin/sh
[ $# -ne 1 ] && exit 1
BIRD=$1
EXC=`mount -t overlayfs | grep overlayfs -c`
[ $EXC > 0 ] && rm -r /etc/init.d/${BIRD} || mv /etc/init.d/${BIRD} /etc/${BIRD}/init.d/${BIRD}.orig
ln -s /etc/${BIRD}/init.d/${BIRD} /etc/init.d/${BIRD}
exit 0

View File

@ -1,7 +0,0 @@
#!/bin/sh
EXC=`mount -t overlayfs | grep overlayfs -c`
[ $EXC > 0 ] && rm -r /etc/init.d/bird6 || mv /etc/init.d/bird6 /etc/bird6/init.d/bird6.orig
ln -s /etc/bird6/init.d/bird6 /etc/init.d/bird6

View File

@ -0,0 +1,41 @@
<%-
-- Only populate textarea through XHR.poll
-- "refresh" is present in the URL (.../log?refresh=1)
if luci.http.formvalue("refresh") then
-- Force HTTP Contents to be "text/plain"
luci.http.prepare_content("text/plain")
local sys = require("luci.sys")
local uci = require "luci.model.uci".cursor()
-- Get Log File from Bird's configuration or leave it empty.
local log_file = uci:get("bird6", "global", "log_file") or ""
local log_size = ""
if log_file then
log_size = sys.exec("du -h " .. log_file .. " | awk '{print $1}'")
-- Gathering last 30 lines of the Log File.
lf = sys.exec("tail -n30 " .. log_file):gsub("\r\n?", "\n")
end
-- Write File used and its contents.
luci.http.write("Using Log File: " .. log_file .. " - File Size: " .. log_size .. "\n" .. lf)
-- Avoid printing the rest of the page (return only text log data)
return
end
-%>
<%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
// Refresh page each second. Use "refresh=1" as trigger.
XHR.poll(1, '<%=url('admin/network/bird6/log')%>', { refresh: 1 }, function(xhrInstance) {
var area = document.getElementById('log')
area.value = xhrInstance.responseText;
});
//]]></script>
<textarea readonly="readonly" style="width: 100%" wrap="on" rows="32" id="log"><%=lf:pcdata()%></textarea>
<%+footer%>

View File

@ -0,0 +1,5 @@
<%+cbi/valueheader%>
<textarea class="cbi-input-textarea" <% if not self.size then %> style="width: 100%; font: normal 11pt 'Courier New'"<% else %> cols="<%=self.size%>"<% end %> data-update="change"<%= attr("name", cbid) .. attr("id", cbid) .. ifattr(self.rows, "rows") .. ifattr(self.wrap, "wrap") .. ifattr(self.readonly, "readonly") %>>
<%-=pcdata(self:cfgvalue(section))-%>
</textarea>
<%+cbi/valuefooter%>