bird-openwrt: BIRD daemon integration with UCI and LuCI configuration 54/head
authorEloi Carbo <eloicaso@gmail.com>
Wed, 10 Sep 2014 10:32:10 +0000 (12:32 +0200)
committerEloi Carbo <eloicaso@gmail.com>
Wed, 10 Sep 2014 10:32:10 +0000 (12:32 +0200)
16 files changed:
bird-openwrt/bird4-openwrt/Makefile [new file with mode: 0644]
bird-openwrt/bird4-openwrt/src/config/bird4 [new file with mode: 0644]
bird-openwrt/bird4-openwrt/src/controller/bird4.lua [new file with mode: 0644]
bird-openwrt/bird4-openwrt/src/init.d/bird4 [new file with mode: 0755]
bird-openwrt/bird4-openwrt/src/model/bgp_proto.lua [new file with mode: 0644]
bird-openwrt/bird4-openwrt/src/model/gen_proto.lua [new file with mode: 0644]
bird-openwrt/bird4-openwrt/src/model/overview.lua [new file with mode: 0644]
bird-openwrt/bird4-openwrt/src/uci-defaults/bird4-uci-install-init.d [new file with mode: 0644]
bird-openwrt/bird6-openwrt/Makefile [new file with mode: 0644]
bird-openwrt/bird6-openwrt/src/config/bird6 [new file with mode: 0644]
bird-openwrt/bird6-openwrt/src/controller/bird6.lua [new file with mode: 0644]
bird-openwrt/bird6-openwrt/src/init.d/bird6 [new file with mode: 0755]
bird-openwrt/bird6-openwrt/src/model/bgp_proto.lua [new file with mode: 0644]
bird-openwrt/bird6-openwrt/src/model/gen_proto.lua [new file with mode: 0644]
bird-openwrt/bird6-openwrt/src/model/overview.lua [new file with mode: 0644]
bird-openwrt/bird6-openwrt/src/uci-defaults/bird6-uci-install-init.d [new file with mode: 0644]

diff --git a/bird-openwrt/bird4-openwrt/Makefile b/bird-openwrt/bird4-openwrt/Makefile
new file mode 100644 (file)
index 0000000..55b5bf9
--- /dev/null
@@ -0,0 +1,90 @@
+# 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)))
diff --git a/bird-openwrt/bird4-openwrt/src/config/bird4 b/bird-openwrt/bird4-openwrt/src/config/bird4
new file mode 100644 (file)
index 0000000..05eaffa
--- /dev/null
@@ -0,0 +1,129 @@
+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'
+
+
diff --git a/bird-openwrt/bird4-openwrt/src/controller/bird4.lua b/bird-openwrt/bird4-openwrt/src/controller/bird4.lua
new file mode 100644 (file)
index 0000000..7b2c56d
--- /dev/null
@@ -0,0 +1,27 @@
+--[[ 
+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
+
diff --git a/bird-openwrt/bird4-openwrt/src/init.d/bird4 b/bird-openwrt/bird4-openwrt/src/init.d/bird4
new file mode 100755 (executable)
index 0000000..8732c16
--- /dev/null
@@ -0,0 +1,411 @@
+#!/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
+}
diff --git a/bird-openwrt/bird4-openwrt/src/model/bgp_proto.lua b/bird-openwrt/bird4-openwrt/src/model/bgp_proto.lua
new file mode 100644 (file)
index 0000000..f546cbb
--- /dev/null
@@ -0,0 +1,239 @@
+--[[ 
+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
+
diff --git a/bird-openwrt/bird4-openwrt/src/model/gen_proto.lua b/bird-openwrt/bird4-openwrt/src/model/gen_proto.lua
new file mode 100644 (file)
index 0000000..91dc470
--- /dev/null
@@ -0,0 +1,200 @@
+--[[ 
+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
+
diff --git a/bird-openwrt/bird4-openwrt/src/model/overview.lua b/bird-openwrt/bird4-openwrt/src/model/overview.lua
new file mode 100644 (file)
index 0000000..5db66eb
--- /dev/null
@@ -0,0 +1,77 @@
+--[[ 
+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
diff --git a/bird-openwrt/bird4-openwrt/src/uci-defaults/bird4-uci-install-init.d b/bird-openwrt/bird4-openwrt/src/uci-defaults/bird4-uci-install-init.d
new file mode 100644 (file)
index 0000000..e58a2cf
--- /dev/null
@@ -0,0 +1,7 @@
+#!/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
diff --git a/bird-openwrt/bird6-openwrt/Makefile b/bird-openwrt/bird6-openwrt/Makefile
new file mode 100644 (file)
index 0000000..53e841e
--- /dev/null
@@ -0,0 +1,91 @@
+# 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)))
diff --git a/bird-openwrt/bird6-openwrt/src/config/bird6 b/bird-openwrt/bird6-openwrt/src/config/bird6
new file mode 100644 (file)
index 0000000..1807df7
--- /dev/null
@@ -0,0 +1,86 @@
+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'
+
diff --git a/bird-openwrt/bird6-openwrt/src/controller/bird6.lua b/bird-openwrt/bird6-openwrt/src/controller/bird6.lua
new file mode 100644 (file)
index 0000000..5ee2729
--- /dev/null
@@ -0,0 +1,27 @@
+--[[ 
+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
+
diff --git a/bird-openwrt/bird6-openwrt/src/init.d/bird6 b/bird-openwrt/bird6-openwrt/src/init.d/bird6
new file mode 100755 (executable)
index 0000000..ed99d27
--- /dev/null
@@ -0,0 +1,421 @@
+#!/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
+}
diff --git a/bird-openwrt/bird6-openwrt/src/model/bgp_proto.lua b/bird-openwrt/bird6-openwrt/src/model/bgp_proto.lua
new file mode 100644 (file)
index 0000000..e243fa6
--- /dev/null
@@ -0,0 +1,237 @@
+--[[ 
+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
+
diff --git a/bird-openwrt/bird6-openwrt/src/model/gen_proto.lua b/bird-openwrt/bird6-openwrt/src/model/gen_proto.lua
new file mode 100644 (file)
index 0000000..5299a5b
--- /dev/null
@@ -0,0 +1,201 @@
+--[[ 
+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
+
diff --git a/bird-openwrt/bird6-openwrt/src/model/overview.lua b/bird-openwrt/bird6-openwrt/src/model/overview.lua
new file mode 100644 (file)
index 0000000..cb85b60
--- /dev/null
@@ -0,0 +1,87 @@
+--[[ 
+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
diff --git a/bird-openwrt/bird6-openwrt/src/uci-defaults/bird6-uci-install-init.d b/bird-openwrt/bird6-openwrt/src/uci-defaults/bird6-uci-install-init.d
new file mode 100644 (file)
index 0000000..95c4944
--- /dev/null
@@ -0,0 +1,7 @@
+#!/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