5 # Required-Start: $local_fs $network $remote_fs $syslog
6 # Required-Stop: $local_fs $network $remote_fs $syslog
7 # Default-Start: 2 3 4 5
9 # Short-Description: start and stop the Frr routing suite
10 # Description: Frr is a routing suite for IP routing protocols like
11 # BGP, OSPF, RIP and others. This script contols the main
12 # daemon "frr" as well as the individual protocol daemons.
16 PATH
=/bin
:/usr
/bin
:/sbin
:/usr
/sbin
17 D_PATH
="@CFG_SBIN@" # /usr/lib/frr
18 C_PATH
="@CFG_SYSCONF@" # /etc/frr
19 V_PATH
="@CFG_STATE@" # /var/run/frr
20 VTYSH
="@vtysh_bin@" # /usr/bin/vtysh
21 FRR_USER
="@enable_user@" # frr
22 FRR_GROUP
="@enable_group@" # frr
23 FRR_VTY_GROUP
="@enable_vty_group@" # frrvty
25 # Local Daemon selection may be done by using /etc/frr/daemons.
26 # See /usr/share/doc/frr/README.Debian.gz for further information.
27 # Keep zebra first and do not list watchfrr!
28 DAEMONS
="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd"
30 RELOAD_SCRIPT
="$D_PATH/frr-reload.py"
31 WATCHFRR_STARTED
="$V_PATH/watchfrr.started"
33 if [ -e /lib
/lsb
/init-functions
]; then
34 .
/lib
/lsb
/init-functions
37 if [ -f $D_PATH/ssd
]; then
40 SSD
=`which start-stop-daemon`
43 # Print the name of the pidfile.
49 # Print the name of the vtysh.
57 test -n "$FRR_USER" && chown
"$FRR_USER" "$1"
58 test -n "$FRR_GROUP" && chgrp
"$FRR_GROUP" "$1"
61 # Check if daemon is started by using the pidfile.
64 [ ! -e `pidfile $1` ] && return 3
65 if [ -n "$2" ] && [ "$2" == "log" ]; then
66 status_of_proc
-p `pidfile $1` $1 $1 && return 0 ||
return $?
68 kill -0 `cat \`pidfile
$1\
`` 2> /dev
/null ||
return 1
73 # Loads the config via vtysh -b if configured to do so.
76 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
77 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf
]; then
82 # Check if the daemon is activated and if its executable and config files
85 # returns: 0=ok, 1=error
88 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
89 # check for daemon binary
90 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
93 # If the integrated config file is used the others are not checked.
94 if [ -r "$C_PATH/frr.conf" ]; then
98 # vtysh_enable has no config file nor binary so skip check.
99 # (Not sure why vtysh_enable is in this list but does not hurt)
100 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
101 # check for config file
103 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
104 touch "$C_PATH/$1-$2.conf"
105 chownfrr
"$C_PATH/$1-$2.conf"
107 elif [ ! -r "$C_PATH/$1.conf" ]; then
108 touch "$C_PATH/$1.conf"
109 chownfrr
"$C_PATH/$1.conf"
115 # Starts the server if it's not alrady running according to the pid file.
116 # The Frr daemons creates the pidfile when starting.
124 if [ "$dmn" = "watchfrr" ]; then
126 # We may need to restart watchfrr if new daemons are added and/or
128 if started
"$dmn" ; then
131 # Echo only once. watchfrr is printed in the stop above
135 if [ -e $WATCHFRR_STARTED ] ; then
139 eval "set - $watchfrr_options"
142 --pidfile=`pidfile $dmn` \
143 --exec "$D_PATH/$dmn" \
148 if [ -e $WATCHFRR_STARTED ] ; then
154 elif [ -n "$inst" ]; then
155 echo -n " $dmn-$inst"
156 if ! check_daemon
$dmn $inst ; then
157 echo -n " (binary does not exist)"
163 --pidfile=`pidfile $dmn-$inst` \
164 --exec "$D_PATH/$dmn" \
166 `eval echo "$""$dmn""_options"` -n "$inst"
169 if ! check_daemon
$dmn; then
170 echo -n " (binary does not exist)"
174 if [ "$valgrind_enable" = "yes" ]; then
177 --pidfile=`pidfile $dmn` \
179 -- --trace-children=no
--leak-check=full
--log-file=/var
/log
/frr
/$dmn-valgrind.log
$D_PATH/$dmn \
180 `eval echo "$""$dmn""_options"`
184 --pidfile=`pidfile $dmn` \
185 --exec "$D_PATH/$dmn" \
187 `eval echo "$""$dmn""_options"`
191 # Start the staticd automatically
192 if [ "$dmn" = "zebra" ]; then
193 echo -n "starting staticd since zebra is running"
194 if ! check_daemon staticd
; then
195 echo -n " (binary does not exist)"
201 --pidfile=`pidfile staticd` \
202 --exec "$D_PATH/staticd" \
204 `eval echo "$"staticd"_options"`
208 # Stop the daemon given in the parameter, printing its name to the terminal.
219 if ! started
"$inst" ; then
223 PIDFILE
=`pidfile $inst`
224 PID
=`cat $PIDFILE 2>/dev/null`
225 kill -2 $PID 2>/dev
/null
227 # Now we have to wait until $DAEMON has _really_ stopped.
229 if test -n "$PID" && kill -0 $PID 2>/dev
/null
; then
230 echo -n " (waiting) ."
232 while kill -0 $PID 2>/dev
/null
; do
234 if [ $cnt -gt 60 ]; then
235 # Waited 120 secs now, fail.
244 rm -f `pidfile $inst`
245 rm -f `vtyfile $inst`
247 if [ "$1" = "zebra" ]; then
248 echo -n "Stopping staticd since zebra is running"
254 # Converts values from /etc/frr/daemons to all-numeric values.
255 convert_daemon_prios
()
257 for name
in $DAEMONS zebra vtysh_enable watchfrr_enable
; do
258 # First, assign the value set by the user to $value
259 eval value
=\
${${name}:0:3}
261 # Daemon not activated or entry missing?
262 if [ "$value" = "no" -o "$value" = "" ]; then value
=0; fi
264 # These strings parsed for backwards compatibility.
265 if [ "$value" = "yes" -o "$value" = "true" ]; then
269 # Zebra is threatened special. It must be between 0=off and the first
270 # user assigned value "1" so we increase all other enabled daemons' values.
271 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value
=`expr "$value" + 1`; fi
273 # If e.g. name is zebra then we set "zebra=yes".
278 # Starts watchfrr for all wanted daemons.
286 # Start the monitor daemon only if desired.
287 if [ 0 -eq "$watchfrr_enable" ]; then
291 # Check variable type
292 if declare -p watchfrr_options |
grep -q '^declare \-a'; then
294 watchfrr_options
="${watchfrr_options[@]}"
297 # Which daemons have been started?
299 for daemon_name
in $DAEMONS; do
300 eval daemon_prio
=\$
$daemon_name
301 if [ "$daemon_prio" -gt 0 ]; then
302 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
303 if [ -n "$daemon_inst" ]; then
304 for inst
in ${daemon_inst}; do
305 eval "inst_disable=\${${daemon_name}_${inst}}"
306 if [ -z ${inst_disable} ] ||
[ ${inst_disable} != 0 ]; then
307 if check_daemon
$daemon_name $inst; then
308 watchfrr_options
="$watchfrr_options ${daemon_name}-${inst}"
313 if check_daemon
$daemon_name; then
314 watchfrr_options
="$watchfrr_options $daemon_name"
321 # Start if at least one daemon is activated.
322 if [ $found_one -eq 1 ]; then
323 echo -n "Starting Frr monitor daemon:"
332 echo -n "Stopping Frr monitor daemon:"
337 # Stops all daemons that have a lower level of priority than the given.
338 # (technically if daemon_prio >= wanted_prio)
347 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
348 daemon
=${BASH_REMATCH[1]}
349 inst
=${BASH_REMATCH[2]}
355 daemon_list
=${daemon:-$DAEMONS}
357 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
359 for prio_i
in `seq 10 -1 $wanted_prio`; do
360 for daemon_name
in $daemon_list; do
361 eval daemon_prio
=\
${${daemon_name}:0:3}
363 if [ $daemon_prio -eq $prio_i ]; then
364 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
365 if [ -n "$daemon_inst" ]; then
366 for i
in ${daemon_inst}; do
367 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
368 stop
"$daemon_name" "$inst"
369 elif [ x
"$inst" == x
]; then
370 stop
"$daemon_name" "$i"
381 if [ -z "$inst" ]; then
382 # Now stop other daemons that're prowling, coz the daemons file changed
383 echo -n "Stopping other frr daemons"
384 if [ -n "$daemon" ]; then
385 eval "file_list_suffix="$V_PATH"/"$daemon*""
387 eval "file_list_suffix="$V_PATH/*""
389 for pidfile
in $file_list_suffix.pid
; do
390 PID
=`cat $pidfile 2>/dev/null`
391 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
397 echo -n "Removing remaining .vty files"
398 for vtyfile
in $file_list_suffix.vty
; do
405 # Starts all daemons that have a higher level of priority than the given.
406 # (technically if daemon_prio <= wanted_prio)
416 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
417 daemon
=${BASH_REMATCH[1]}
418 inst
=${BASH_REMATCH[2]}
424 daemon_list
=${daemon:-$DAEMONS}
426 echo -n "Starting Frr daemons (prio:$wanted_prio):"
428 for prio_i
in `seq 1 $wanted_prio`; do
429 for daemon_name
in $daemon_list; do
430 eval daemon_prio
=\$
${daemon_name}
432 if [ $daemon_prio -eq $prio_i ]; then
433 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
434 if [ -n "$daemon_inst" ]; then
435 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
436 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
439 # Check if we're starting again by switching from single instance
441 if started
"$daemon_name"; then
442 PIDFILE
=`pidfile $daemon_name`
444 --stop --quiet --oknodo \
445 --pidfile "$PIDFILE" \
446 --exec "$D_PATH/$daemon_name"
452 for i
in ${daemon_inst}; do
453 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
454 start
"$daemon_name" "$inst"
455 elif [ x
"$inst" == x
]; then
456 start
"$daemon_name" "$i"
460 # Check if we're starting again by switching from
461 # single instance to MI version
462 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
463 for pidfile
in $file_list_suffix.pid
; do
464 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
468 for vtyfile
in $file_list_suffix.vty
; do
485 local failed_status
=0
487 if [ -n "$1" ] && [[ "$1" =~
(.
*)-(.
*) ]]; then
488 daemon
=${BASH_REMATCH[1]}
489 inst
=${BASH_REMATCH[2]}
494 daemon_list
=${daemon:-$DAEMONS}
496 # Which daemons have been started?
497 for daemon_name
in $daemon_list; do
498 eval daemon_prio
=\$
$daemon_name
499 if [ "$daemon_prio" -gt 0 ]; then
500 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
501 if [ -n "$daemon_inst" ]; then
502 for i
in ${daemon_inst}; do
503 if [ -n "$inst" -a "$inst" = "$i" ]; then
504 started
"$1" "log" || failed_status
=$?
505 elif [ -z "$inst" ]; then
506 started
"$daemon_name-$i" "log" || failed_status
=$?
510 started
"$daemon_name" "log" || failed_status
=$?
515 # All daemons that need to have been started are up and running
516 return $failed_status
519 #########################################################
521 #########################################################
523 # Config broken but script must exit silently.
524 [ ! -r "$C_PATH/daemons" ] && exit 0
528 .
"$C_PATH/daemons.conf"
530 # Read configuration variable file if it is present
531 [ -r /etc
/default
/frr
] && .
/etc
/default
/frr
533 MAX_INSTANCES
=${MAX_INSTANCES:=5}
535 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
538 if [ ! -d $V_PATH ]; then
539 echo "Creating $V_PATH"
545 if [ -n "$3" ] && [ "$3" != "all" ]; then
547 elif [ -n "$2" ] && [ "$2" != "all" ]; then
553 # Try to load this necessary (at least for 2.6) module.
554 if [ -d /lib
/modules
/`uname -r` ] ; then
555 echo "Loading capability module if not yet done."
556 set +e
; LC_ALL
=C modprobe
-a capability
2>&1 |
egrep -v "(not found|Can't locate)"; set -e
561 if [ "$2" != "watchfrr" ]; then
568 1|
2|
3|
4|
5|
6|
7|
8|
9|
10)
569 # Stop/start daemons for the appropriate priority level
576 # Stop all daemons at level '0' or 'stop'
578 if [ "$dmn" != "watchfrr" ]; then
579 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
583 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
584 echo "Removing all routes made by FRR."
585 # Specific values for each proto can be found
586 # in /etc/iproute2/rt_protos as well as FRR
587 # specific ones in /etc/iproute2/rt_protos.d
588 # Additionally if a new protocol is added
589 # we need to add it here as well as
590 # in rt_netlink.h( follow the directions! )
591 ip route flush proto
4
592 ip route flush proto
11
593 ip route flush proto
42
594 ip route flush proto
186
595 ip route flush proto
187
596 ip route flush proto
188
597 ip route flush proto
189
598 ip route flush proto
190
599 ip route flush proto
191
600 ip route flush proto
192
601 ip route flush proto
193
602 ip route flush proto
194
603 ip route flush proto
195
604 ip route flush proto
196
606 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
612 # Just apply the commands that have changed, no restart necessary
613 if [ ! -x "$RELOAD_SCRIPT" ]; then
614 echo "Please install frr-pythontools package. Required for reload"
618 NEW_CONFIG_FILE
="${2:-$C_PATH/frr.conf}"
619 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
620 echo "Applying only incremental changes to running configuration from frr.conf"
621 "$RELOAD_SCRIPT" --reload $C_PATH/frr.conf
630 restart|force-reload
)
637 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
638 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
639 echo " reload applies only modifications from the running config to all daemons."
640 echo " reload neither restarts starts any daemon nor starts any new ones."
641 echo " Read /usr/share/doc/frr/README.Debian for details."
646 echo "Exiting from the script"