--- /dev/null
+# Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+# BGP/Bird integration with OpenWRT and QMP
+#
+# 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/>.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+BIRD:=bird4
+PKG_NAME:=$(BIRD)-openwrt
+PKG_RELEASE:=0.2
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+uci:=$(BIRD)-uci
+luci:=luci-app-$(BIRD)
+
+
+include $(INCLUDE_DIR)/package.mk
+
+define Build/Prepare
+endef
+define Build/Compile
+endef
+
+define Package/$(uci)
+ TITLE:=The BIRD UCI module
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Routing and Redirection
+ MAINTAINER:=Eloi Carbo <eloicaso@openmailbox.org>
+ URL:=https://github.com/eloicaso/bird4-openwrt/
+ DEPENDS:=+$(BIRD) +libuci +uci
+endef
+
+define Package/$(uci)/description
+$(BIRD) UCI integration module
+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/
+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
+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/
+ DEPENDS:=+$(BIRD)-uci +luci-base
+endef
+
+define Package/$(luci)/description
+$(BIRD) application for LuCI
+endef
+
+define Package/$(luci)/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller/
+ $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/$(BIRD)/
+ $(CP) ./src/model/* $(1)/usr/lib/lua/luci/model/cbi/$(BIRD)/
+ $(CP) ./src/controller/* $(1)/usr/lib/lua/luci/controller/
+endef
+
+$(eval $(call BuildPackage,$(luci)))
--- /dev/null
+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'
+
+
--- /dev/null
+--[[
+Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+BGP/Bird integration with OpenWRT and QMP
+
+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/>.
+--]]
+
+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
+
--- /dev/null
+#!/bin/sh /etc/rc.common
+
+# Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+# BGP/Bird integration with OpenWRT and QMP
+#
+# 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="bird4"
+BIRD_CONFIG="/etc/$BIRD.conf"
+
+START=99
+STOP=10
+
+SERVICE_DAEMONIZE=1
+SERVICE_USE_PID=1
+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 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
+}
+
+start() {
+ config_load bird4
+ 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
+ else
+ #Set Bird4 configuration location:
+ local UCI_config_File
+ get UCI_config_File 'bird'
+ BIRD_CONFIG=${UCI_config_File:-/tmp/bird4.conf}
+ #Setup the basic configuration
+ prepare_global 'global'
+ 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_bgp_template 'bgp_template'
+ config_foreach prepare_bgp 'bgp'
+ config_foreach prepare_bgp_filters 'filter'
+ #Start the service
+ service_start $BIRD_BIN -d -c $BIRD_CONFIG -P $SERVICE_PID_FILE
+ fi
+}
+
+stop() {
+ service_stop $BIRD_BIN
+}
+
+restart() {
+ stop
+ start
+}
+
+
+reload() {
+ service_reload $BIRD_BIN
+}
--- /dev/null
+--[[
+Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+BGP/Bird integration with OpenWRT and QMP
+
+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/>.
+--]]
+
+require("luci.sys")
+local http = require "luci.http"
+local uci = require "luci.model.uci"
+local uciout = uci.cursor()
+
+m=Map("bird4", "Bird4 BGP protocol's configuration")
+
+tab_templates = {}
+uciout:foreach('bird4', 'bgp_template', function (s)
+ local name = s[".name"]
+ if (name ~= nil) then
+ table.insert(tab_templates, name)
+ end
+end)
+
+-- Section 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",
+ function (s)
+ table:value(s.name)
+ end)
+table:value("")
+
+import = sect_templates:option(Value, "import", "Import","")
+import.optional=true
+export = sect_templates:option(Value, "export", "Export", "")
+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
+
+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
+next_hop_self.optional = true
+
+next_hop_keep = sect_templates:option(Flag, "next_hop_keep", "Next hop keep", "Forward the received Next Hop attribute event in situations where the local address should be used instead, like subneting")
+next_hop_keep.default = nil
+next_hop_keep.optional = true
+
+rr_client = sect_templates:option(Flag, "rr_client", "Route Reflector server", "This router serves as a Route Reflector server and treats neighbors as clients")
+rr_client.default = nil
+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_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: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
+
+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_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: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_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: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:
+
+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("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
+
+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
+
+next_hop_keep = sect_instances:option(Flag, "next_hop_keep", "Next hop keep", "Forward the received Next Hop attribute event in situations where the local address should be used instead, like subneting")
+next_hop_keep.default = nil
+next_hop_keep.optional = true
+
+rr_client = sect_instances:option(Flag, "rr_client", "Route Reflector server", "This router serves as a Route Reflector server and treats neighbors as clients")
+rr_client.default = nil
+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_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: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
+
+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_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: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_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: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
+
+
+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')
+end
+
+return m
+
--- /dev/null
+--[[
+Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+BGP/Bird integration with OpenWRT and QMP
+
+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/>.
+--]]
+
+require("luci.sys")
+local http = require "luci.http"
+local uci = require "luci.model.uci"
+local uciout = uci.cursor()
+
+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"]="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"}}
+}
+
+local routeroptions = {
+ {["name"]="prefix",["help"]="",["depends"]={"router","special","iface","multipath","recursive"}},
+ {["name"]="via",["help"]="",["depends"]={"router","multipath"}},
+ {["name"]="attribute",["help"]="",["depends"]={"special"}},
+ {["name"]="iface",["help"]="",["depends"]={"iface"}},
+ {["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
+
+-- Optional parameters
+for _,o in ipairs(protoptions) do
+ if o.name ~= nil then
+ for _, d in ipairs(o.depends) do
+ if d == "kernel" then
+ if o.name == "learn" or o.name == "persist" then
+ 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",
+ function (s)
+ value:value(s.name)
+ end)
+ value:value("")
+ else
+ value = sect_kernel_protos:option(Value, o.name, translate(o.name), translate(o.help))
+ end
+ value.optional = true
+ value.rmempty = true
+ end
+ end
+
+ 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
+
+-- Default kernel parameters
+
+disabled = sect_device_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 == "device" then
+ value = sect_device_protos:option(Value, o.name, translate(o.name), translate(o.help))
+ value.optional = true
+ value.rmempty = true
+ end
+ end
+ end
+end
+
+--
+-- 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
+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",
+ function (s)
+ instance:value(s[".name"])
+ end)
+
+prefix = sect_routes:option(Value, "prefix", "Route prefix", "")
+
+type = sect_routes:option(ListValue, "type", "Type of route", "")
+type:value("router")
+type:value("special")
+type:value("iface")
+type:value("recursive")
+type:value("multipath")
+
+valueVia = sect_routes:option(Value, "via", "Via", "")
+valueVia.optional = false
+valueVia:depends("type", "router")
+valueVia.datatype = "ip4addr"
+
+listVia = sect_routes:option(DynamicList, "l_via", "Via", "")
+listVia:depends("type", "multipath")
+listVia.optional=false
+listVia.datatype = "ip4addr"
+
+attribute = sect_routes:option(Value, "attribute", "Attribute", "Types are: unreachable, prohibit and blackhole")
+attribute:depends("type", "special")
+
+iface = sect_routes:option(ListValue, "iface", "Interface", "")
+iface:depends("type", "iface")
+
+uciout:foreach("wireless", "wifi-iface",
+ function(section)
+ iface:value(section[".name"])
+ end)
+
+ip = sect_routes:option(Value, "ip", "IP address", "")
+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')
+end
+
+return m
+
--- /dev/null
+--[[
+Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+BGP/Bird integration with OpenWRT and QMP
+
+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/>.
+]]--
+
+require("luci.sys")
+local http = require "luci.http"
+local uci = require "luci.model.uci"
+local uciout = uci.cursor()
+
+m=Map("bird4", "Bird4 UCI configuration helper", "")
+
+-- Named section: "bird"
+
+s_bird_uci = m:section(NamedSection, "bird", "bird", "Bird4 file settings", "")
+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.default = "/tmp/bird4.conf"
+
+-- Named Section: "table"
+
+s_bird_table = m:section(TypedSection, "table", "Tables configuration", "Configuration of the tables used in the protocols")
+s_bird_table.addremove = true
+s_bird_table.anonymous = true
+
+name = s_bird_table:option(Value, "name", "Table name", "Descriptor ID of the table")
+
+-- Named section: "global"
+
+s_bird_global = m:section(NamedSection, "global", "global", "Global options", "Basic Bird4 settings")
+s_bird_global.addremove = False
+
+id = s_bird_global:option(Value, "router_id", "Router ID", "Identification number of the router. By default, is the router's IP.")
+
+lf = s_bird_global:option(Value, "log_file", "Log File", "File used to store log related data.")
+
+l = s_bird_global:option(MultiValue, "log", "Log", "Set which elements do you want to log.")
+l:value("all", "All")
+l:value("info", "Info")
+l:value("warning","Warning")
+l:value("error","Error")
+l:value("fatal","Fatal")
+l:value("debug","Debug")
+l:value("trace","Trace")
+l:value("remote","Remote")
+l:value("auth","Auth")
+
+d = s_bird_global:option(MultiValue, "debug", "Debug", "Set which elements do you want to debug.")
+d:value("all", "All")
+d:value("states","States")
+d:value("routes","Routes")
+d:value("filters","Filters")
+d:value("interfaces","Interfaces")
+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')
+end
+
+return m
--- /dev/null
+#!/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
--- /dev/null
+# Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+# BGP/Bird integration with OpenWRT and QMP
+#
+# 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/>.
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+BIRD:=bird6
+PKG_NAME:=$(BIRD)-openwrt
+PKG_RELEASE:=0.2
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+uci:=$(BIRD)-uci
+luci:=luci-app-$(BIRD)
+
+
+include $(INCLUDE_DIR)/package.mk
+
+define Build/Prepare
+endef
+define Build/Compile
+endef
+
+define Package/$(uci)
+ TITLE:=The BIRD UCI module
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Routing and Redirection
+ MAINTAINER:=Eloi Carbo <eloicaso@openmailbox.org>
+ URL:=https://github.com/eloicaso/bird6-openwrt/
+ DEPENDS:=+$(BIRD) +libuci +uci
+endef
+
+define Package/$(uci)/description
+$(BIRD) UCI integration module
+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/
+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
+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/
+ DEPENDS:=+$(BIRD)-uci +luci-base
+endef
+
+define Package/$(luci)/description
+$(BIRD) application for LuCI
+endef
+
+define Package/$(luci)/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller/
+ $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/$(BIRD)/
+ $(CP) ./src/model/* $(1)/usr/lib/lua/luci/model/cbi/$(BIRD)/
+ $(CP) ./src/controller/* $(1)/usr/lib/lua/luci/controller/
+endef
+
+$(eval $(call BuildPackage,$(luci)))
--- /dev/null
+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.
+
+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'
+
+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 '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'
+
+config filter 'firstFilter'
+ option type 'bgp'
+ option instance 'bgp1'
+ option file_path '/var/filters/f1'
+
--- /dev/null
+--[[
+Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+BGP/Bird integration with OpenWRT and QMP
+
+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/>.
+--]]
+
+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
+
--- /dev/null
+#!/bin/sh /etc/rc.common
+
+# Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+# BGP/Bird integration with OpenWRT and QMP
+#
+# 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="bird6"
+BIRD_CONFIG="/etc/$BIRD.conf"
+
+START=99
+STOP=10
+
+SERVICE_DAEMONIZE=1
+SERVICE_USE_PID=1
+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
+}
+
+
+start() {
+ config_load bird6
+ 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
+ else
+ #Set Bird6 configuration location:
+ local UCI_config_File
+ get UCI_config_File 'bird'
+ BIRD_CONFIG=${UCI_config_File:-/tmp/bird6.conf}
+ #Setup the basic configuration
+ prepare_global 'global'
+ 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_bgp_template 'bgp_template'
+ config_foreach prepare_bgp 'bgp'
+ config_foreach prepare_bgp_filters 'filter'
+ #Start the service
+ service_start $BIRD_BIN -d -c $BIRD_CONFIG -P $SERVICE_PID_FILE
+ fi
+}
+
+stop() {
+ service_stop $BIRD_BIN
+}
+
+restart() {
+ stop
+ start
+}
+
+
+reload() {
+ service_reload $BIRD_BIN
+}
--- /dev/null
+--[[
+Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+BGP/Bird integration with OpenWRT and QMP
+
+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/>.
+--]]
+
+require("luci.sys")
+local http = require "luci.http"
+local uci = require "luci.model.uci"
+local uciout = uci.cursor()
+
+m=Map("bird6", "Bird6 BGP protocol's configuration")
+
+tab_templates = {}
+uciout:foreach('bird6', 'bgp_template', function (s)
+ local name = s[".name"]
+ if (name ~= nil) then
+ table.insert(tab_templates, name)
+ end
+end)
+
+-- Section 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("bird6", "table",
+ function (s)
+ table:value(s.name)
+ end)
+table:value("")
+
+import = sect_templates:option(Value, "import", "Import","")
+import.optional=true
+export = sect_templates:option(Value, "export", "Export", "")
+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
+
+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
+next_hop_self.optional = true
+
+next_hop_keep = sect_templates:option(Flag, "next_hop_keep", "Next hop keep", "Forward the received Next Hop attribute event in situations where the local address should be used instead, like subneting")
+next_hop_keep.default = nil
+next_hop_keep.optional = true
+
+rr_client = sect_templates:option(Flag, "rr_client", "Route Reflector server", "This router serves as a Route Reflector server and treats neighbors as clients")
+rr_client.default = nil
+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_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: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
+
+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_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: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_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: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:
+
+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",
+ 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("")
+
+description = sect_instances:option(TextValue, "description", "Description", "Description of the current BGP instance")
+description.optional = true
+
+import = sect_instances:option(Value, "import", "Import","")
+import.optional=true
+export = sect_instances:option(Value, "export", "Export", "")
+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
+
+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
+
+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
+
+next_hop_keep = sect_instances:option(Flag, "next_hop_keep", "Next hop keep", "Forward the received Next Hop attribute event in situations where the local address should be used instead, like subneting")
+next_hop_keep.default = nil
+next_hop_keep.optional = true
+
+rr_client = sect_instances:option(Flag, "rr_client", "Route Reflector server", "This router serves as a Route Reflector server and treats neighbors as clients")
+rr_client.default = nil
+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_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: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
+
+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_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: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_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: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")
+
+function m.on_commit(self,map)
+ luci.sys.call('/etc/init.d/bird6 stop; /etc/init.d/bird6 start')
+end
+
+return m
+
--- /dev/null
+--[[
+Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+BGP/Bird integration with OpenWRT and QMP
+
+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/>.
+--]]
+
+require("luci.sys")
+local http = require "luci.http"
+local uci = require "luci.model.uci"
+local uciout = uci.cursor()
+
+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"]="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"}}
+}
+
+local routeroptions = {
+ {["name"]="prefix",["help"]="",["depends"]={"router","special","iface","multipath","recursive"}},
+ {["name"]="via",["help"]="",["depends"]={"router","multipath"}},
+ {["name"]="attribute",["help"]="",["depends"]={"special"}},
+ {["name"]="iface",["help"]="",["depends"]={"iface"}},
+ {["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
+
+-- Optional parameters
+for _,o in ipairs(protoptions) do
+ if o.name ~= nil then
+ for _, d in ipairs(o.depends) do
+ if d == "kernel" then
+ if o.name == "learn" or o.name == "persist" then
+ 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",
+ function (s)
+ value:value(s.name)
+ end)
+ value:value("")
+ else
+ value = sect_kernel_protos:option(Value, o.name, translate(o.name), translate(o.help))
+ end
+ value.optional = true
+ value.rmempty = true
+ end
+ end
+
+ 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
+
+-- Default kernel parameters
+
+disabled = sect_device_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 == "device" then
+ value = sect_device_protos:option(Value, o.name, translate(o.name), translate(o.help))
+ value.optional = true
+ value.rmempty = true
+ end
+ end
+ end
+end
+
+--
+-- 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("bird6", "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
+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("bird6", "static",
+ function (s)
+ instance:value(s[".name"])
+ end)
+
+prefix = sect_routes:option(Value, "prefix", "Route prefix", "")
+prefix.datatype = "ip6prefix"
+
+type = sect_routes:option(ListValue, "type", "Type of route", "")
+type:value("router")
+type:value("special")
+type:value("iface")
+type:value("recursive")
+type:value("multipath")
+
+valueVia = sect_routes:option(Value, "via", "Via", "")
+valueVia.optional = false
+valueVia:depends("type", "router")
+valueVia.datatype = "ip6addr"
+
+listVia = sect_routes:option(DynamicList, "l_via", "Via", "")
+listVia:depends("type", "multipath")
+listVia.optional=false
+listVia.datatype = "ip6addr"
+
+attribute = sect_routes:option(Value, "attribute", "Attribute", "Types are: unreachable, prohibit and blackhole")
+attribute:depends("type", "special")
+
+iface = sect_routes:option(ListValue, "iface", "Interface", "")
+iface:depends("type", "iface")
+
+uciout:foreach("wireless", "wifi-iface",
+ function(section)
+ iface:value(section[".name"])
+ end)
+
+ip = sect_routes:option(Value, "ip", "IP address", "")
+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')
+end
+
+return m
+
--- /dev/null
+--[[
+Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
+BGP/Bird integration with OpenWRT and QMP
+
+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/>.
+]]--
+
+require("luci.sys")
+local http = require "luci.http"
+local uci = require "luci.model.uci"
+local uciout = uci.cursor()
+
+m=Map("bird6", "Bird6 UCI configuration helper", "")
+
+-- Named section: "bird"
+
+s_bird_uci = m:section(NamedSection, "bird", "bird", "Bird6 file settings", "")
+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.default = "/tmp/bird6.conf"
+
+-- Named Section: "table"
+
+s_bird_table = m:section(TypedSection, "table", "Tables configuration", "Configuration of the tables used in the protocols")
+s_bird_table.addremove = true
+s_bird_table.anonymous = true
+
+name = s_bird_table:option(Value, "name", "Table name", "Descriptor ID of the table")
+
+-- Named section: "global"
+
+s_bird_global = m:section(NamedSection, "global", "global", "Global options", "Basic Bird6 settings")
+s_bird_global.addremove = False
+
+id = s_bird_global:option(Value, "router_id", "Router ID", "Identification number of the router. By default, is the router's IP.")
+
+lf = s_bird_global:option(Value, "log_file", "Log File", "File used to store log related data.")
+
+l = s_bird_global:option(MultiValue, "log", "Log", "Set which elements do you want to log.")
+l:value("all", "All")
+l:value("info", "Info")
+l:value("warning","Warning")
+l:value("error","Error")
+l:value("fatal","Fatal")
+l:value("debug","Debug")
+l:value("trace","Trace")
+l:value("remote","Remote")
+l:value("auth","Auth")
+
+d = s_bird_global:option(MultiValue, "debug", "Debug", "Set which elements do you want to debug.")
+d:value("all", "All")
+d:value("states","States")
+d:value("routes","Routes")
+d:value("filters","Filters")
+d:value("interfaces","Interfaces")
+d:value("events","Events")
+d:value("packets","Packets")
+
+listen_addr = s_bird_global:option(Value, "listen_bgp_addr", "BGP Address", "Set the Addres that BGP will listen to.")
+listen_addr.optional = true
+
+listen_port = s_bird_global:option(Value, "listen_bgp_port", "BGP Port", "Set the port that BGP will listen to.")
+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')
+end
+
+return m
--- /dev/null
+#!/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