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
21 # Local Daemon selection may be done by using /etc/frr/daemons.
22 # See /usr/share/doc/frr/README.Debian.gz for further information.
23 # Keep zebra first and do not list watchfrr!
24 DAEMONS
="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd"
26 RELOAD_SCRIPT
=/usr
/lib
/frr
/frr-reload.py
28 if [ -e /lib
/lsb
/init-functions
]; then
29 .
/lib
/lsb
/init-functions
32 if [ -f /usr
/lib
/frr
/ssd
]; then
35 SSD
=`which start-stop-daemon`
38 # Print the name of the pidfile.
44 # Print the name of the vtysh.
50 # Check if daemon is started by using the pidfile.
53 [ ! -e `pidfile $1` ] && return 3
54 if [ -n "$2" ] && [ "$2" == "log" ]; then
55 status_of_proc
-p `pidfile $1` $1 $1 && return 0 ||
return $?
57 kill -0 `cat \`pidfile
$1\
`` 2> /dev
/null ||
return 1
62 # Loads the config via vtysh -b if configured to do so.
65 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
66 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf
]; then
71 # Check if the daemon is activated and if its executable and config files
74 # returns: 0=ok, 1=error
77 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
78 # check for daemon binary
79 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
82 # If the integrated config file is used the others are not checked.
83 if [ -r "$C_PATH/frr.conf" ]; then
87 # vtysh_enable has no config file nor binary so skip check.
88 # (Not sure why vtysh_enable is in this list but does not hurt)
89 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
90 # check for config file
92 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
93 touch "$C_PATH/$1-$2.conf"
94 chown frr
:frr
"$C_PATH/$1-$2.conf"
96 elif [ ! -r "$C_PATH/$1.conf" ]; then
97 touch "$C_PATH/$1.conf"
98 chown frr
:frr
"$C_PATH/$1.conf"
104 # Starts the server if it's not alrady running according to the pid file.
105 # The Frr daemons creates the pidfile when starting.
109 if [ "$1" = "watchfrr" ]; then
111 # We may need to restart watchfrr if new daemons are added and/or
113 if started
"$1" ; then
116 # Echo only once. watchfrr is printed in the stop above
120 if [ -e /var
/run
/frr
/watchfrr.started
] ; then
121 rm /var
/run
/frr
/watchfrr.started
125 --pidfile=`pidfile $1` \
126 --exec "$D_PATH/$1" \
128 "${watchfrr_options[@]}"
131 if [ -e /var
/run
/frr
/watchfrr.started
] ; then
137 elif [ -n "$2" ]; then
139 if ! check_daemon
$1 $2 ; then
140 echo -n " (binary does not exist)"
146 --pidfile=`pidfile $1-$2` \
147 --exec "$D_PATH/$1" \
149 `eval echo "$""$1""_options"` -n "$2"
152 if ! check_daemon
$1; then
153 echo -n " (binary does not exist)"
157 if [ "$valgrind_enable" = "yes" ]; then
160 --pidfile=`pidfile $1` \
162 -- --trace-children=no
--leak-check=full
--log-file=/var
/log
/frr
/$1-valgrind.log
$D_PATH/$1 \
163 `eval echo "$""$1""_options"`
167 --pidfile=`pidfile $1` \
168 --exec "$D_PATH/$1" \
170 `eval echo "$""$1""_options"`
174 # Start the staticd automatically
175 if [ "$1" = "zebra" ]; then
176 echo -n "starting staticd since zebra is running"
177 if ! check_daemon staticd
; then
178 echo -n " (binary does not exist)"
184 --pidfile=`pidfile staticd` \
185 --exec "$D_PATH/staticd" \
187 `eval echo "$"staticd"_options"`
191 # Stop the daemon given in the parameter, printing its name to the terminal.
202 if ! started
"$inst" ; then
206 PIDFILE
=`pidfile $inst`
207 PID
=`cat $PIDFILE 2>/dev/null`
208 kill -2 $PID 2>/dev
/null
210 # Now we have to wait until $DAEMON has _really_ stopped.
212 if test -n "$PID" && kill -0 $PID 2>/dev
/null
; then
213 echo -n " (waiting) ."
215 while kill -0 $PID 2>/dev
/null
; do
217 if [ $cnt -gt 60 ]; then
218 # Waited 120 secs now, fail.
227 rm -f `pidfile $inst`
228 rm -f `vtyfile $inst`
230 if [ "$1" = "zebra" ]; then
231 echo -n "Stopping staticd since zebra is running"
237 # Converts values from /etc/frr/daemons to all-numeric values.
238 convert_daemon_prios
()
240 for name
in $DAEMONS zebra vtysh_enable watchfrr_enable
; do
241 # First, assign the value set by the user to $value
242 eval value
=\
${${name}:0:3}
244 # Daemon not activated or entry missing?
245 if [ "$value" = "no" -o "$value" = "" ]; then value
=0; fi
247 # These strings parsed for backwards compatibility.
248 if [ "$value" = "yes" -o "$value" = "true" ]; then
252 # Zebra is threatened special. It must be between 0=off and the first
253 # user assigned value "1" so we increase all other enabled daemons' values.
254 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value
=`expr "$value" + 1`; fi
256 # If e.g. name is zebra then we set "zebra=yes".
261 # Starts watchfrr for all wanted daemons.
269 # Start the monitor daemon only if desired.
270 if [ 0 -eq "$watchfrr_enable" ]; then
274 # Check variable type
275 if ! declare -p watchfrr_options |
grep -q '^declare \-a'; then
277 echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!"
278 echo "ERROR: Please convert config file and restart!"
282 # Which daemons have been started?
284 for daemon_name
in $DAEMONS; do
285 eval daemon_prio
=\$
$daemon_name
286 if [ "$daemon_prio" -gt 0 ]; then
287 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
288 if [ -n "$daemon_inst" ]; then
289 for inst
in ${daemon_inst}; do
290 eval "inst_disable=\${${daemon_name}_${inst}}"
291 if [ -z ${inst_disable} ] ||
[ ${inst_disable} != 0 ]; then
292 if check_daemon
$daemon_name $inst; then
293 watchfrr_options
+=("${daemon_name}-${inst}")
298 if check_daemon
$daemon_name; then
299 watchfrr_options
+=($daemon_name)
306 # Start if at least one daemon is activated.
307 if [ $found_one -eq 1 ]; then
308 echo -n "Starting Frr monitor daemon:"
317 echo -n "Stopping Frr monitor daemon:"
322 # Stops all daemons that have a lower level of priority than the given.
323 # (technically if daemon_prio >= wanted_prio)
332 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
333 daemon
=${BASH_REMATCH[1]}
334 inst
=${BASH_REMATCH[2]}
340 daemon_list
=${daemon:-$DAEMONS}
342 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
344 for prio_i
in `seq 10 -1 $wanted_prio`; do
345 for daemon_name
in $daemon_list; do
346 eval daemon_prio
=\
${${daemon_name}:0:3}
348 if [ $daemon_prio -eq $prio_i ]; then
349 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
350 if [ -n "$daemon_inst" ]; then
351 for i
in ${daemon_inst}; do
352 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
353 stop
"$daemon_name" "$inst"
354 elif [ x
"$inst" == x
]; then
355 stop
"$daemon_name" "$i"
366 if [ -z "$inst" ]; then
367 # Now stop other daemons that're prowling, coz the daemons file changed
368 echo -n "Stopping other frr daemons"
369 if [ -n "$daemon" ]; then
370 eval "file_list_suffix="$V_PATH"/"$daemon*""
372 eval "file_list_suffix="$V_PATH/*""
374 for pidfile
in $file_list_suffix.pid
; do
375 PID
=`cat $pidfile 2>/dev/null`
376 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
382 echo -n "Removing remaining .vty files"
383 for vtyfile
in $file_list_suffix.vty
; do
390 # Starts all daemons that have a higher level of priority than the given.
391 # (technically if daemon_prio <= wanted_prio)
401 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
402 daemon
=${BASH_REMATCH[1]}
403 inst
=${BASH_REMATCH[2]}
409 daemon_list
=${daemon:-$DAEMONS}
411 echo -n "Starting Frr daemons (prio:$wanted_prio):"
413 for prio_i
in `seq 1 $wanted_prio`; do
414 for daemon_name
in $daemon_list; do
415 eval daemon_prio
=\$
${daemon_name}
417 if [ $daemon_prio -eq $prio_i ]; then
418 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
419 if [ -n "$daemon_inst" ]; then
420 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
421 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
424 # Check if we're starting again by switching from single instance
426 if started
"$daemon_name"; then
427 PIDFILE
=`pidfile $daemon_name`
429 --stop --quiet --oknodo \
430 --pidfile "$PIDFILE" \
431 --exec "$D_PATH/$daemon_name"
437 for i
in ${daemon_inst}; do
438 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
439 start
"$daemon_name" "$inst"
440 elif [ x
"$inst" == x
]; then
441 start
"$daemon_name" "$i"
445 # Check if we're starting again by switching from
446 # single instance to MI version
447 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
448 for pidfile
in $file_list_suffix.pid
; do
449 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
453 for vtyfile
in $file_list_suffix.vty
; do
470 local failed_status
=0
472 if [ -n "$1" ] && [[ "$1" =~
(.
*)-(.
*) ]]; then
473 daemon
=${BASH_REMATCH[1]}
474 inst
=${BASH_REMATCH[2]}
479 daemon_list
=${daemon:-$DAEMONS}
481 # Which daemons have been started?
482 for daemon_name
in $daemon_list; do
483 eval daemon_prio
=\$
$daemon_name
484 if [ "$daemon_prio" -gt 0 ]; then
485 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
486 if [ -n "$daemon_inst" ]; then
487 for i
in ${daemon_inst}; do
488 if [ -n "$inst" -a "$inst" = "$i" ]; then
489 started
"$1" "log" || failed_status
=$?
490 elif [ -z "$inst" ]; then
491 started
"$daemon_name-$i" "log" || failed_status
=$?
495 started
"$daemon_name" "log" || failed_status
=$?
500 # All daemons that need to have been started are up and running
501 return $failed_status
504 #########################################################
506 #########################################################
508 # Config broken but script must exit silently.
509 [ ! -r "$C_PATH/daemons" ] && exit 0
513 .
"$C_PATH/daemons.conf"
515 # Read configuration variable file if it is present
516 [ -r /etc
/default
/frr
] && .
/etc
/default
/frr
518 MAX_INSTANCES
=${MAX_INSTANCES:=5}
520 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
523 if [ ! -d $V_PATH ]; then
524 echo "Creating $V_PATH"
526 chown frr
:frr
$V_PATH
530 if [ -n "$3" ] && [ "$3" != "all" ]; then
532 elif [ -n "$2" ] && [ "$2" != "all" ]; then
538 # Try to load this necessary (at least for 2.6) module.
539 if [ -d /lib
/modules
/`uname -r` ] ; then
540 echo "Loading capability module if not yet done."
541 set +e
; LC_ALL
=C modprobe
-a capability
2>&1 |
egrep -v "(not found|Can't locate)"; set -e
546 if [ "$2" != "watchfrr" ]; then
553 1|
2|
3|
4|
5|
6|
7|
8|
9|
10)
554 # Stop/start daemons for the appropriate priority level
561 # Stop all daemons at level '0' or 'stop'
563 if [ "$dmn" != "watchfrr" ]; then
564 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
568 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
569 echo "Removing all routes made by FRR."
570 # Specific values for each proto can be found
571 # in /etc/iproute2/rt_protos as well as FRR
572 # specific ones in /etc/iproute2/rt_protos.d
573 # Additionally if a new protocol is added
574 # we need to add it here as well as
575 # in rt_netlink.h( follow the directions! )
576 ip route flush proto
4
577 ip route flush proto
11
578 ip route flush proto
42
579 ip route flush proto
186
580 ip route flush proto
187
581 ip route flush proto
188
582 ip route flush proto
189
583 ip route flush proto
190
584 ip route flush proto
191
585 ip route flush proto
192
586 ip route flush proto
193
587 ip route flush proto
194
588 ip route flush proto
195
589 ip route flush proto
196
591 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
597 # Just apply the commands that have changed, no restart necessary
598 [ ! -x "$RELOAD_SCRIPT" ] && echo "frr-reload script not available" && exit 0
599 NEW_CONFIG_FILE
="${2:-$C_PATH/frr.conf}"
600 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
601 echo "Applying only incremental changes to running configuration from frr.conf"
602 "$RELOAD_SCRIPT" --reload /etc
/frr
/frr.conf
611 restart|force-reload
)
618 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
619 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
620 echo " reload applies only modifications from the running config to all daemons."
621 echo " reload neither restarts starts any daemon nor starts any new ones."
622 echo " Read /usr/share/doc/frr/README.Debian for details."
627 echo "Exiting from the script"