mirror of
https://git.openwrt.org/feed/routing.git
synced 2024-06-16 12:14:10 +02:00
422 lines
16 KiB
Plaintext
422 lines
16 KiB
Plaintext
![]() |
#!/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
|
||
|
}
|