bird-openwrt: BIRD daemon integration with UCI and LuCI configuration
[feed/routing.git] / bird-openwrt / bird4-openwrt / src / init.d / bird4
1 #!/bin/sh /etc/rc.common
2
3 # Copyright (C) 2014 - Eloi Carbó Solé (GSoC2014)
4 # BGP/Bird integration with OpenWRT and QMP
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #
19
20 BIRD="bird4"
21 BIRD_CONFIG="/etc/$BIRD.conf"
22
23 START=99
24 STOP=10
25
26 SERVICE_DAEMONIZE=1
27 SERVICE_USE_PID=1
28 SERVICE_PID_FILE="/var/run/$BIRD.pid"
29
30 BIRD_BIN="/usr/sbin/$BIRD"
31
32
33 # Function: writeToConfig $1
34 # $1 string.
35 # Allows to write in the $BIRD_CONFIG file, the string $1. This function does not check the $1 string.
36 # Example: writeToConfig "value: $N"
37 writeToConfig() {
38 echo "$1" >> $BIRD_CONFIG
39 }
40
41 # Function: write $1 $2
42 # $1 string. $2 string.
43 # This function checks if $2 is empty. If not, it writes the string $1 in the $BIRD_CONFIG file.
44 # Use write function to check if $1, value found inside $2, is not empty and can be written in the configuration file.
45 # Example: N=""; write "value: $N" $N;
46 write() {
47 [ -n "$2" ] && writeToConfig "$1"
48 }
49
50 #Function: write_bool $1 $2
51 # $1 string; $2 boolean
52 # This function checks if $2 is true or false and write the $1 string into $BIRD_CONFIG file.
53 # The function writes a # before the $2 string if its false.
54 # Example: local N=0; write_bool $N
55 write_bool() {
56 [ "$2" == 0 ] && writeToConfig "# $1;" || writeToConfig " $1;"
57 }
58
59 # Function: get $1 $2
60 # $1 string. $2 string
61 # This function uses the external UCI function "config_get $result $section $option" to obtain a string value from UCI config file.
62 # To use this function, use the same name of the UCI option for the variable.
63 # Example: UCI (option id 'abcd'); local id; get id $section
64 get() {
65 config_get $1 $2 $1
66 }
67
68 # Function: get_bool $1 $2
69 # $1 boolean. $2 string
70 # This function uses the external UCI function "config_get_bool $result $section $option" to obtain a boolean value from UCI config file.
71 # To use this function, use the same name of the UCI option for the variable $1.
72 # Example: UCI (option use_ipv6 '1'); local use_ipv6; get use_ipv6 $section
73 get_bool() {
74 config_get_bool $1 $2 $1
75 }
76
77 # Function: multipath_list $1
78 # $1 string
79 # This function writes the $1 string in the multipath routes.
80 multipath_list() {
81 write " via $1" $1
82 }
83
84 # Function: prepare_tables $1
85 # $1 string
86 # This function gets each "table" section in the UCI configuration and sets each option in the bird4.conf file.
87 # $1 is set as the ID of the current UCI table section
88 prepare_tables() {
89 local section="$1"; local name
90 get name $section
91 write "table $name;" $name
92 }
93
94 # Function: prepare_global $1
95 # $1 string
96 # This function gets each "global" section in the UCI configuration and sets each option in the bird4.conf file.
97 # $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.
98 prepare_global () {
99 local section="$1"
100 local log_file; local log; local debug; local router_id; local table
101
102 # Remove old configuration file
103 rm -f "$BIRD_CONFIG"
104
105 get log_file $section
106 get log $section
107 get debug $section
108 get router_id $section
109 get table $section
110
111 # First line of the NEW configuration file
112 echo "#Bird4 configuration using UCI:" > $BIRD_CONFIG
113 writeToConfig " "
114 [ -n "$log_file" -a -n "$log" ] && writeToConfig 'log "'$log_file'" '$log';'
115 write "debug protocols $debug;" $debug
116 writeToConfig " "
117 writeToConfig "#Router ID"
118 write "router id $router_id;" $router_id
119 writeToConfig " "
120 writeToConfig "#Secondary tables"
121 config_foreach prepare_tables 'table'
122 writeToConfig " "
123 }
124
125 # Function: prepare_routes $1
126 # $1 string
127 # This function gets each "route" section in the UCI configuration and sets each option in the bird4.conf file.
128 # $1 is set as the ID of the current UCI route section. Each type of route has its own treatment.
129 prepare_routes() {
130 local instance; local prefix; local via; local type
131 local section="$1"
132 local protoInstance="$2"
133 get instance $section
134
135 if [ "$instance" = "$protoInstance" ]; then
136 get type $section
137 case "$type" in
138 "router")
139 get prefix $section
140 get via $section
141 [ -n "$prefix" -a -n "$via" ] && writeToConfig " route $prefix via $via;"
142 ;;
143 "special")
144 get prefix $section
145 get attribute $section
146 [ -n "$prefix" -a -n "$attribute" ] && writeToConfig " route $prefix $attribute;"
147 ;;
148 "iface")
149 get prefix $section
150 get iface $section
151 [ -n "$prefix" -a -n "$iface" ] && writeToConfig ' route '$prefix' via "'$iface'";'
152 ;;
153 "multipath")
154 get prefix $section
155 write " route $prefix multipath" $prefix
156 config_list_foreach $section l_via multipath_list
157 writeToConfig " ;"
158 ;;
159 esac
160 fi
161 }
162
163 # Function: prepare_kernel $1
164 # $1 string
165 # This function gets each "kernel" protocol section in the UCI configuration and sets each option in the bird6.conf file.
166 # $1 is set as the ID of the current UCI kernel section.
167 prepare_kernel() {
168 local section="$1"
169 write "#$section configuration:" $section
170 local disabled; local table; local kernel_table; local import; local export; local scan_time; local persist; local learn
171 get_bool disabled $section
172 get table $section
173 get import $section
174 get export $section
175 get scan_time $section
176 get kernel_table $section
177 get learn $section
178 get persist $section
179 writeToConfig "protocol kernel {"
180 write_bool disabled $disabled
181 write " table $table;" $table
182 write " kernel table $kernel_table;" $kernel_table
183 write_bool learn $learn
184 write_bool persist $persist
185 write " scan time $scan_time;" $scan_time
186 write " import $import;" $import
187 write " export $export;" $export
188 writeToConfig "}"
189 writeToConfig " "
190 }
191
192 # Function: prepare_static $1
193 # $1 string
194 # This function gets each "static" protocol section in the UCI configuration and sets each option in the bird6.conf file.
195 # $1 is set as the ID of the current UCI static section.
196 prepare_static() {
197 local section="$1"
198 local disabled
199 get disabled $section
200 if [ "$disabled" -eq 0 ]; then
201 local table
202 get table $section
203 writeToConfig "#$section configration:" $section
204 writeToConfig "protocol static {"
205 write " table $table;" $table
206 config_foreach prepare_routes 'route' $section
207 writeToConfig "}"
208 writeToConfig " "
209 fi
210 }
211
212 # Function: prepare_device $1
213 # $1 string
214 # This function gets each "device" protocol section in the UCI configuration and sets each option in the bird4.conf file.
215 # $1 is set as the ID of the current UCI device section.
216 prepare_device() {
217 local section="$1"
218 local disabled; local scan_time
219 get disabled $section
220 get scan_time $section
221 write "#$section configuration:" $section
222 writeToConfig "protocol device {"
223 write_bool disabled $disabled
224 write " scan time $scan_time;" $scan_time
225 writeToConfig "}"
226 writeToConfig " "
227 }
228
229 # Function: prepare_bgp_template $1
230 # $1 string
231 # This function gets each "bgp_template" protocol section in the UCI configuration and sets each option in the bird4.conf file.
232 # $1 is set as the ID of the current UCI bgp_template section.
233 # Careful! Template options will be replaced by "instance" options if there is any match.
234 prepare_bgp_template() {
235 local section="$1"
236 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
237 get_bool disabled $section
238 get_bool next_hop_self $section
239 get_bool next_hop_keep $section
240 get table $section
241 get import $section
242 get export $section
243 get local_address $section
244 get local_as $section
245 get rr_client $section
246 get rr_cluster_id $section
247 get import_limit $section
248 get import_limit_action $section
249 get export_limit $section
250 get export_limit_action $section
251 get receive_limit $section
252 get receive_limit_action $section
253 get neighbor_address $section
254 get neighbor_as $section
255
256 writeToConfig "#$section template:"
257 writeToConfig "template bgp $section {"
258 [ -n "$disabled" ] && write_bool disabled $disabled
259 write " table $table;" $table
260 write " local as $local_as;" $local_as
261 write " source address $local_address;" $local_address
262 write " import $import;" $import
263 write " export $export;" $export
264 if [ -n "$next_hop_self" ]; then
265 [ "$next_hop_self" = "1" ] && writeToConfig " next hop self;" || writeToConfig "# next hop self;"
266 fi
267 if [ -n "$next_hop_keep" ]; then
268 [ "$next_hop_keep" = "1" ] && writeToConfig " next hop keep;" || writeToConfig "# next hop keep;"
269 fi
270 [ "$rr_client" = "1" ] && writeToConfig " rr client;" || writeToConfig "# rr client;"
271 write " rr cluster id $rr_cluster_id;" $rr_cluster_id
272 if [ -n "$import_limit" -a "$import_limit" > "0" ]; then
273 [ -z "$import_limit_action" ] && $import_limit_action = "warn"
274 writeToConfig " import limit $import_limit action $import_limit_action;"
275 fi
276 if [ -n "$export_limit" -a "$export_limit" > "0" ]; then
277 [ -z "$export_limit_action" ] && $export_limit_action = "warn"
278 writeToConfig " export limit $export_limit action $export_limit_action;"
279 fi
280 if [ -n "$receive_limit" -a "$receive_limit" > "0" ]; then
281 [ -z "$receive_limit_action" ] && $receive_limit_action = "warn"
282 writeToConfig " receive limit $receive_limit action $receive_limit_action;"
283 fi
284 [ -n "$neighbor_address" -a -n "$neighbor_as" ] && writeToConfig " neighbor $neighbor_address as $neighbor_as;"
285 writeToConfig "}"
286 writeToConfig " "
287 }
288
289 # Function: prepare_bgp $1
290 # $1 string
291 # This function gets each "bgp" protocol section in the UCI configuration and sets each option in the bird6.conf file.
292 # $1 is set as the ID of the current UCI bgp section.
293 # Careful! The options set in bgp instances overlap bgp_template ones.
294 prepare_bgp() {
295 local section="$1"
296 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
297 get disabled $section
298 get table $section
299 get template $section
300 get description $section
301 get import $section
302 get export $section
303 get local_address $section
304 get local_as $section
305 get rr_client $section
306 get rr_cluster_id $section
307 get import_limit $section
308 get import_limit_action $section
309 get export_limit $section
310 get export_limit_action $section
311 get receive_limit $section
312 get receive_limit_action $section
313 get neighbor_address $section
314 get neighbor_as $section
315
316 writeToConfig "#$section configuration:"
317 [ -n "$template" ] && writeToConfig "protocol bgp $section from $template {" || writeToConfig "protocol bgp $section {"
318 [ -n "$disabled" ] && write_bool disabled $disabled
319 write " table $table;" $table
320 # [ -n "$description" ] && writeToConfig ' description "'$description'";'
321 write " local as $local_as;" $local_as
322 write " source address $local_address;" $local_address
323 write " import $import;" $import
324 write " export $export;" $export
325 if [ -n "$next_hop_self" ]; then
326 [ "$next_hop_self" = "1" ] && writeToConfig " next hop self;" || writeToConfig "# next hop self;"
327 fi
328 if [ -n "$next_hop_keep" ]; then
329 [ "$next_hop_keep" = "1" ] && writeToConfig " next hop keep;" || writeToConfig "# next hop keep;"
330 fi
331 [ "$rr_client" = "1" ] && writeToConfig " rr client;" || writeToConfig "# rr client;"
332 write " rr cluster id $rr_cluster_id;" $rr_cluster_id
333 if [ -n "$import_limit" -a "$import_limit" > "0" ]; then
334 [ -z "$import_limit_action" ] && $import_limit_action = "warn"
335 writeToConfig " import limit $import_limit action $import_limit_action;"
336 fi
337 if [ -n "$export_limit" -a "$export_limit" > "0" ]; then
338 [ -z "$export_limit_action" ] && $export_limit_action = "warn"
339 writeToConfig " export limit $export_limit action $export_limit_action;"
340 fi
341 if [ -n "$receive_limit" -a "$receive_limit" > "0" ]; then
342 [ -z "$receive_limit_action" ] && $receive_limit_action = "warn"
343 writeToConfig " receive limit $receive_limit action $receive_limit_action;"
344 fi
345 [ -n "$neighbor_address" -a -n "$neighbor_as" ] && writeToConfig " neighbor $neighbor_address as $neighbor_as;"
346 writeToConfig "}"
347 writeToConfig " "
348 }
349
350 # Function: prepare_bgp_filters $1
351 # $1 string
352 # This function gets each "bgp_filter" protocol section in the UCI configuration and sets each option in the bird4.conf file.
353 # $1 is set as the ID of the current UCI bgp_filter section.
354 # This function checks if the filter file exists and, in that case, it writes its content to the configuration file.
355 prepare_bgp_filters() {
356 local section="$1"
357 local type
358 local file_path
359 get type $section
360 get file_path $section
361 if [ -e "$file_path" ]; then
362 local filter_content=`cat $file_path`
363 if [ -n "$type" -a "$type" = "bgp" ]; then
364 writeToConfig "#Filter $section:"
365 writeToConfig "${filter_content}"
366 writeToConfig " "
367 fi
368 fi
369 }
370
371 start() {
372 config_load bird4
373 local use_UCI_config
374 get use_UCI_config 'bird'
375
376 if [ -z "$use_UCI_config" -o "$use_UCI_config" = "0" ]; then
377 service_start $BIRD_BIN -d -c $BIRD_CONFIG -P $SERVICE_PID_FILE
378 else
379 #Set Bird4 configuration location:
380 local UCI_config_File
381 get UCI_config_File 'bird'
382 BIRD_CONFIG=${UCI_config_File:-/tmp/bird4.conf}
383 #Setup the basic configuration
384 prepare_global 'global'
385 config_foreach prepare_kernel 'kernel'
386 config_foreach prepare_static 'static'
387 config_foreach prepare_device 'device'
388 #config_foreach prepare_direct 'direct'
389
390 #Setup the protocols configuration (currently BGP only)
391 config_foreach prepare_bgp_template 'bgp_template'
392 config_foreach prepare_bgp 'bgp'
393 config_foreach prepare_bgp_filters 'filter'
394 #Start the service
395 service_start $BIRD_BIN -d -c $BIRD_CONFIG -P $SERVICE_PID_FILE
396 fi
397 }
398
399 stop() {
400 service_stop $BIRD_BIN
401 }
402
403 restart() {
404 stop
405 start
406 }
407
408
409 reload() {
410 service_reload $BIRD_BIN
411 }