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"
26 RELOAD_SCRIPT
=/usr
/lib
/frr
/frr-reload.py
28 .
/lib
/lsb
/init-functions
30 if [ -f /usr
/lib
/frr
/ssd
]; then
33 SSD
=`which start-stop-daemon`
36 # Print the name of the pidfile.
42 # Print the name of the vtysh.
48 # Check if daemon is started by using the pidfile.
51 [ ! -e `pidfile $1` ] && return 3
52 if [ -n "$2" ] && [ "$2" == "log" ]; then
53 status_of_proc
-p `pidfile $1` $1 $1 && return 0 ||
return $?
55 kill -0 `cat \`pidfile
$1\
`` 2> /dev
/null ||
return 1
60 # Loads the config via vtysh -b if configured to do so.
63 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
64 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf
]; then
69 # Check if the daemon is activated and if its executable and config files
72 # returns: 0=ok, 1=error
75 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
76 # check for daemon binary
77 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
80 # If the integrated config file is used the others are not checked.
81 if [ -r "$C_PATH/frr.conf" ]; then
85 # vtysh_enable has no config file nor binary so skip check.
86 # (Not sure why vtysh_enable is in this list but does not hurt)
87 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
88 # check for config file
90 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
91 touch "$C_PATH/$1-$2.conf"
92 chown frr
:frr
"$C_PATH/$1-$2.conf"
94 elif [ ! -r "$C_PATH/$1.conf" ]; then
95 touch "$C_PATH/$1.conf"
96 chown frr
:frr
"$C_PATH/$1.conf"
102 # Starts the server if it's not alrady running according to the pid file.
103 # The Frr daemons creates the pidfile when starting.
107 if [ "$1" = "watchfrr" ]; then
109 # We may need to restart watchfrr if new daemons are added and/or
111 if started
"$1" ; then
114 # Echo only once. watchfrr is printed in the stop above
118 if [ -e /var
/run
/frr
/watchfrr.started
] ; then
119 rm /var
/run
/frr
/watchfrr.started
123 --pidfile=`pidfile $1` \
124 --exec "$D_PATH/$1" \
126 "${watchfrr_options[@]}"
129 if [ -e /var
/run
/frr
/watchfrr.started
] ; then
135 elif [ -n "$2" ]; then
137 if ! check_daemon
$1 $2 ; then
138 echo -n " (binary does not exist)"
144 --pidfile=`pidfile $1-$2` \
145 --exec "$D_PATH/$1" \
147 `eval echo "$""$1""_options"` -n "$2"
150 if ! check_daemon
$1; then
151 echo -n " (binary does not exist)"
155 if [ "$valgrind_enable" = "yes" ]; then
158 --pidfile=`pidfile $1` \
160 -- --trace-children=no
--leak-check=full
--log-file=/var
/log
/frr
/$1-valgrind.log
$D_PATH/$1 \
161 `eval echo "$""$1""_options"`
165 --pidfile=`pidfile $1` \
166 --exec "$D_PATH/$1" \
168 `eval echo "$""$1""_options"`
173 # Stop the daemon given in the parameter, printing its name to the terminal.
184 if ! started
"$inst" ; then
188 PIDFILE
=`pidfile $inst`
189 PID
=`cat $PIDFILE 2>/dev/null`
190 ${SSD} --stop --quiet --retry=TERM
/30/KILL
/5 --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1"
192 # Now we have to wait until $DAEMON has _really_ stopped.
194 if test -n "$PID" && kill -0 $PID 2>/dev
/null
; then
195 echo -n " (waiting) ."
197 while kill -0 $PID 2>/dev
/null
; do
199 if [ $cnt -gt 60 ]; then
200 # Waited 120 secs now, fail.
209 rm -f `pidfile $inst`
210 rm -f `vtyfile $inst`
214 # Converts values from /etc/frr/daemons to all-numeric values.
215 convert_daemon_prios
()
217 for name
in $DAEMONS zebra vtysh_enable watchfrr_enable
; do
218 # First, assign the value set by the user to $value
219 eval value
=\
${${name}:0:3}
221 # Daemon not activated or entry missing?
222 if [ "$value" = "no" -o "$value" = "" ]; then value
=0; fi
224 # These strings parsed for backwards compatibility.
225 if [ "$value" = "yes" -o "$value" = "true" ]; then
229 # Zebra is threatened special. It must be between 0=off and the first
230 # user assigned value "1" so we increase all other enabled daemons' values.
231 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value
=`expr "$value" + 1`; fi
233 # If e.g. name is zebra then we set "zebra=yes".
238 # Starts watchfrr for all wanted daemons.
246 # Start the monitor daemon only if desired.
247 if [ 0 -eq "$watchfrr_enable" ]; then
251 # Check variable type
252 if ! declare -p watchfrr_options |
grep -q '^declare \-a'; then
254 echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!"
255 echo "ERROR: Please convert config file and restart!"
259 # Which daemons have been started?
261 for daemon_name
in $DAEMONS; do
262 eval daemon_prio
=\$
$daemon_name
263 if [ "$daemon_prio" -gt 0 ]; then
264 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
265 if [ -n "$daemon_inst" ]; then
266 for inst
in ${daemon_inst}; do
267 eval "inst_disable=\${${daemon_name}_${inst}}"
268 if [ -z ${inst_disable} ] ||
[ ${inst_disable} != 0 ]; then
269 if check_daemon
$daemon_name $inst; then
270 watchfrr_options
+=("${daemon_name}-${inst}")
275 if check_daemon
$daemon_name; then
276 watchfrr_options
+=($daemon_name)
283 # Start if at least one daemon is activated.
284 if [ $found_one -eq 1 ]; then
285 echo -n "Starting Frr monitor daemon:"
294 echo -n "Stopping Frr monitor daemon:"
299 # Stops all daemons that have a lower level of priority than the given.
300 # (technically if daemon_prio >= wanted_prio)
309 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
310 daemon
=${BASH_REMATCH[1]}
311 inst
=${BASH_REMATCH[2]}
317 daemon_list
=${daemon:-$DAEMONS}
319 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
321 for prio_i
in `seq 10 -1 $wanted_prio`; do
322 for daemon_name
in $daemon_list; do
323 eval daemon_prio
=\
${${daemon_name}:0:3}
325 if [ $daemon_prio -eq $prio_i ]; then
326 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
327 if [ -n "$daemon_inst" ]; then
328 for i
in ${daemon_inst}; do
329 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
330 stop
"$daemon_name" "$inst"
331 elif [ x
"$inst" == x
]; then
332 stop
"$daemon_name" "$i"
343 if [ -z "$inst" ]; then
344 # Now stop other daemons that're prowling, coz the daemons file changed
345 echo -n "Stopping other frr daemons"
346 if [ -n "$daemon" ]; then
347 eval "file_list_suffix="$V_PATH"/"$daemon*""
349 eval "file_list_suffix="$V_PATH/*""
351 for pidfile
in $file_list_suffix.pid
; do
352 PID
=`cat $pidfile 2>/dev/null`
353 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
359 echo -n "Removing remaining .vty files"
360 for vtyfile
in $file_list_suffix.vty
; do
367 # Starts all daemons that have a higher level of priority than the given.
368 # (technically if daemon_prio <= wanted_prio)
378 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
379 daemon
=${BASH_REMATCH[1]}
380 inst
=${BASH_REMATCH[2]}
386 daemon_list
=${daemon:-$DAEMONS}
388 echo -n "Starting Frr daemons (prio:$wanted_prio):"
390 for prio_i
in `seq 1 $wanted_prio`; do
391 for daemon_name
in $daemon_list; do
392 eval daemon_prio
=\$
${daemon_name}
394 if [ $daemon_prio -eq $prio_i ]; then
395 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
396 if [ -n "$daemon_inst" ]; then
397 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
398 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
401 # Check if we're starting again by switching from single instance
403 if started
"$daemon_name"; then
404 PIDFILE
=`pidfile $daemon_name`
406 --stop --quiet --oknodo \
407 --pidfile "$PIDFILE" \
408 --exec "$D_PATH/$daemon_name"
414 for i
in ${daemon_inst}; do
415 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
416 start
"$daemon_name" "$inst"
417 elif [ x
"$inst" == x
]; then
418 start
"$daemon_name" "$i"
422 # Check if we're starting again by switching from
423 # single instance to MI version
424 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
425 for pidfile
in $file_list_suffix.pid
; do
426 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
430 for vtyfile
in $file_list_suffix.vty
; do
447 local failed_status
=0
449 if [ -n "$1" ] && [[ "$1" =~
(.
*)-(.
*) ]]; then
450 daemon
=${BASH_REMATCH[1]}
451 inst
=${BASH_REMATCH[2]}
456 daemon_list
=${daemon:-$DAEMONS}
458 # Which daemons have been started?
459 for daemon_name
in $daemon_list; do
460 eval daemon_prio
=\$
$daemon_name
461 if [ "$daemon_prio" -gt 0 ]; then
462 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
463 if [ -n "$daemon_inst" ]; then
464 for i
in ${daemon_inst}; do
465 if [ -n "$inst" -a "$inst" = "$i" ]; then
466 started
"$1" "log" || failed_status
=$?
467 elif [ -z "$inst" ]; then
468 started
"$daemon_name-$i" "log" || failed_status
=$?
472 started
"$daemon_name" "log" || failed_status
=$?
477 # All daemons that need to have been started are up and running
478 return $failed_status
481 #########################################################
483 #########################################################
485 # Config broken but script must exit silently.
486 [ ! -r "$C_PATH/daemons" ] && exit 0
490 .
"$C_PATH/daemons.conf"
492 # Read configuration variable file if it is present
493 [ -r /etc
/default
/frr
] && .
/etc
/default
/frr
495 MAX_INSTANCES
=${MAX_INSTANCES:=5}
497 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
500 if [ ! -d $V_PATH ]; then
501 echo "Creating $V_PATH"
503 chown frr
:frr
$V_PATH
507 if [ -n "$3" ] && [ "$3" != "all" ]; then
509 elif [ -n "$2" ] && [ "$2" != "all" ]; then
515 # Try to load this necessary (at least for 2.6) module.
516 if [ -d /lib
/modules
/`uname -r` ] ; then
517 echo "Loading capability module if not yet done."
518 set +e
; LC_ALL
=C modprobe
-a capability
2>&1 |
egrep -v "(not found|Can't locate)"; set -e
523 if [ "$2" != "watchfrr" ]; then
530 1|
2|
3|
4|
5|
6|
7|
8|
9|
10)
531 # Stop/start daemons for the appropriate priority level
538 # Stop all daemons at level '0' or 'stop'
540 if [ "$dmn" != "watchfrr" ]; then
541 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
545 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
546 echo "Removing all routes made by FRR."
547 ip route flush proto bgp
548 ip route flush proto ospf
549 ip route flush proto static
550 ip route flush proto rip
551 ip route flush proto ripng
552 ip route flush proto zebra
553 ip route flush proto isis
556 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
562 # Just apply the commands that have changed, no restart necessary
563 [ ! -x "$RELOAD_SCRIPT" ] && echo "frr-reload script not available" && exit 0
564 NEW_CONFIG_FILE
="${2:-$C_PATH/frr.conf}"
565 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
566 echo "Applying only incremental changes to running configuration from frr.conf"
567 "$RELOAD_SCRIPT" --reload /etc
/frr
/frr.conf
576 restart|force-reload
)
583 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
584 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
585 echo " reload applies only modifications from the running config to all daemons."
586 echo " reload neither restarts starts any daemon nor starts any new ones."
587 echo " Read /usr/share/doc/frr/README.Debian for details."
592 echo "Exiting from the script"