From 1dc4a6ae00bb72c327b199e883cba867506578c1 Mon Sep 17 00:00:00 2001 From: Eloi Carbo Date: Wed, 10 Sep 2014 12:32:10 +0200 Subject: [PATCH] bird-openwrt: BIRD daemon integration with UCI and LuCI configuration --- bird-openwrt/bird4-openwrt/Makefile | 90 ++++ bird-openwrt/bird4-openwrt/src/config/bird4 | 129 ++++++ .../bird4-openwrt/src/controller/bird4.lua | 27 ++ bird-openwrt/bird4-openwrt/src/init.d/bird4 | 411 +++++++++++++++++ .../bird4-openwrt/src/model/bgp_proto.lua | 239 ++++++++++ .../bird4-openwrt/src/model/gen_proto.lua | 200 +++++++++ .../bird4-openwrt/src/model/overview.lua | 77 ++++ .../src/uci-defaults/bird4-uci-install-init.d | 7 + bird-openwrt/bird6-openwrt/Makefile | 91 ++++ bird-openwrt/bird6-openwrt/src/config/bird6 | 86 ++++ .../bird6-openwrt/src/controller/bird6.lua | 27 ++ bird-openwrt/bird6-openwrt/src/init.d/bird6 | 421 ++++++++++++++++++ .../bird6-openwrt/src/model/bgp_proto.lua | 237 ++++++++++ .../bird6-openwrt/src/model/gen_proto.lua | 201 +++++++++ .../bird6-openwrt/src/model/overview.lua | 87 ++++ .../src/uci-defaults/bird6-uci-install-init.d | 7 + 16 files changed, 2337 insertions(+) create mode 100644 bird-openwrt/bird4-openwrt/Makefile create mode 100644 bird-openwrt/bird4-openwrt/src/config/bird4 create mode 100644 bird-openwrt/bird4-openwrt/src/controller/bird4.lua create mode 100755 bird-openwrt/bird4-openwrt/src/init.d/bird4 create mode 100644 bird-openwrt/bird4-openwrt/src/model/bgp_proto.lua create mode 100644 bird-openwrt/bird4-openwrt/src/model/gen_proto.lua create mode 100644 bird-openwrt/bird4-openwrt/src/model/overview.lua create mode 100644 bird-openwrt/bird4-openwrt/src/uci-defaults/bird4-uci-install-init.d create mode 100644 bird-openwrt/bird6-openwrt/Makefile create mode 100644 bird-openwrt/bird6-openwrt/src/config/bird6 create mode 100644 bird-openwrt/bird6-openwrt/src/controller/bird6.lua create mode 100755 bird-openwrt/bird6-openwrt/src/init.d/bird6 create mode 100644 bird-openwrt/bird6-openwrt/src/model/bgp_proto.lua create mode 100644 bird-openwrt/bird6-openwrt/src/model/gen_proto.lua create mode 100644 bird-openwrt/bird6-openwrt/src/model/overview.lua create mode 100644 bird-openwrt/bird6-openwrt/src/uci-defaults/bird6-uci-install-init.d diff --git a/bird-openwrt/bird4-openwrt/Makefile b/bird-openwrt/bird4-openwrt/Makefile new file mode 100644 index 0000000..55b5bf9 --- /dev/null +++ b/bird-openwrt/bird4-openwrt/Makefile @@ -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 . +# + +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 + 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 + 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 index 0000000..05eaffa --- /dev/null +++ b/bird-openwrt/bird4-openwrt/src/config/bird4 @@ -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 index 0000000..7b2c56d --- /dev/null +++ b/bird-openwrt/bird4-openwrt/src/controller/bird4.lua @@ -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 . +--]] + +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 index 0000000..8732c16 --- /dev/null +++ b/bird-openwrt/bird4-openwrt/src/init.d/bird4 @@ -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 . +# + +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 index 0000000..f546cbb --- /dev/null +++ b/bird-openwrt/bird4-openwrt/src/model/bgp_proto.lua @@ -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 . +--]] + +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 index 0000000..91dc470 --- /dev/null +++ b/bird-openwrt/bird4-openwrt/src/model/gen_proto.lua @@ -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 . +--]] + +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 index 0000000..5db66eb --- /dev/null +++ b/bird-openwrt/bird4-openwrt/src/model/overview.lua @@ -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 . +]]-- + +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 index 0000000..e58a2cf --- /dev/null +++ b/bird-openwrt/bird4-openwrt/src/uci-defaults/bird4-uci-install-init.d @@ -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 index 0000000..53e841e --- /dev/null +++ b/bird-openwrt/bird6-openwrt/Makefile @@ -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 . +# + +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 + 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 + 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 index 0000000..1807df7 --- /dev/null +++ b/bird-openwrt/bird6-openwrt/src/config/bird6 @@ -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 index 0000000..5ee2729 --- /dev/null +++ b/bird-openwrt/bird6-openwrt/src/controller/bird6.lua @@ -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 . +--]] + +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 index 0000000..ed99d27 --- /dev/null +++ b/bird-openwrt/bird6-openwrt/src/init.d/bird6 @@ -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 . +# + +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 index 0000000..e243fa6 --- /dev/null +++ b/bird-openwrt/bird6-openwrt/src/model/bgp_proto.lua @@ -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 . +--]] + +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 index 0000000..5299a5b --- /dev/null +++ b/bird-openwrt/bird6-openwrt/src/model/gen_proto.lua @@ -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 . +--]] + +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 index 0000000..cb85b60 --- /dev/null +++ b/bird-openwrt/bird6-openwrt/src/model/overview.lua @@ -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 . +]]-- + +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 index 0000000..95c4944 --- /dev/null +++ b/bird-openwrt/bird6-openwrt/src/uci-defaults/bird6-uci-install-init.d @@ -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 -- 2.30.2