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"
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 the integrated config file is used the others are not checked.
76 if [ -r "$C_PATH/frr.conf" ]; then
80 # vtysh_enable has no config file nor binary so skip check.
81 # (Not sure why vtysh_enable is in this list but does not hurt)
82 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
83 # check for daemon binary
84 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
86 # check for config file
88 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
89 touch "$C_PATH/$1-$2.conf"
90 chown frr
:frr
"$C_PATH/$1-$2.conf"
92 elif [ ! -r "$C_PATH/$1.conf" ]; then
93 touch "$C_PATH/$1.conf"
94 chown frr
:frr
"$C_PATH/$1.conf"
100 # Starts the server if it's not alrady running according to the pid file.
101 # The Frr daemons creates the pidfile when starting.
105 if [ "$1" = "watchfrr" ]; then
107 # We may need to restart watchfrr if new daemons are added and/or
109 if started
"$1" ; then
112 # Echo only once. watchfrr is printed in the stop above
116 if [ -e /var
/run
/frr
/watchfrr.started
] ; then
117 rm /var
/run
/frr
/watchfrr.started
121 --pidfile=`pidfile $1` \
122 --exec "$D_PATH/$1" \
124 "${watchfrr_options[@]}"
127 if [ -e /var
/run
/frr
/watchfrr.started
] ; then
133 elif [ -n "$2" ]; then
135 if ! check_daemon
$1 $2 ; then
136 echo -n " (binary does not exist)"
142 --pidfile=`pidfile $1-$2` \
143 --exec "$D_PATH/$1" \
145 `eval echo "$""$1""_options"` -n "$2"
148 if ! check_daemon
$1; then
149 echo -n " (binary does not exist)"
153 if [ $valgrind_enable = "yes" ]; then
156 --pidfile=`pidfile $1` \
157 --exec "/usr/bin/valgrind" \
158 -- --trace-children=no
--leak-check=full
--log-file=/var
/log
/frr
/$1-valgrind.log
$D_PATH/$1 \
159 `eval echo "$""$1""_options"`
163 --pidfile=`pidfile $1` \
164 --exec "$D_PATH/$1" \
166 `eval echo "$""$1""_options"`
171 # Stop the daemon given in the parameter, printing its name to the terminal.
182 if ! started
"$inst" ; then
186 PIDFILE
=`pidfile $inst`
187 PID
=`cat $PIDFILE 2>/dev/null`
188 ${SSD} --stop --quiet --retry=TERM
/30/KILL
/5 --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1"
190 # Now we have to wait until $DAEMON has _really_ stopped.
192 if test -n "$PID" && kill -0 $PID 2>/dev
/null
; then
193 echo -n " (waiting) ."
195 while kill -0 $PID 2>/dev
/null
; do
197 if [ $cnt -gt 60 ]; then
198 # Waited 120 secs now, fail.
207 rm -f `pidfile $inst`
208 rm -f `vtyfile $inst`
212 # Converts values from /etc/frr/daemons to all-numeric values.
213 convert_daemon_prios
()
215 for name
in $DAEMONS zebra vtysh_enable watchfrr_enable
; do
216 # First, assign the value set by the user to $value
217 eval value
=\
${${name}:0:3}
219 # Daemon not activated or entry missing?
220 if [ "$value" = "no" -o "$value" = "" ]; then value
=0; fi
222 # These strings parsed for backwards compatibility.
223 if [ "$value" = "yes" -o "$value" = "true" ]; then
227 # Zebra is threatened special. It must be between 0=off and the first
228 # user assigned value "1" so we increase all other enabled daemons' values.
229 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value
=`expr "$value" + 1`; fi
231 # If e.g. name is zebra then we set "zebra=yes".
236 # Starts watchfrr for all wanted daemons.
244 # Start the monitor daemon only if desired.
245 if [ 0 -eq "$watchfrr_enable" ]; then
249 # Check variable type
250 if ! declare -p watchfrr_options |
grep -q '^declare \-a'; then
252 echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!"
253 echo "ERROR: Please convert config file and restart!"
257 # Which daemons have been started?
259 for daemon_name
in $DAEMONS; do
260 eval daemon_prio
=\$
$daemon_name
261 if [ "$daemon_prio" -gt 0 ]; then
262 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
263 if [ -n "$daemon_inst" ]; then
264 for inst
in ${daemon_inst}; do
265 eval "inst_disable=\${${daemon_name}_${inst}}"
266 if [ -z ${inst_disable} ] ||
[ ${inst_disable} != 0 ]; then
267 if check_daemon
$daemon_name $inst; then
268 watchfrr_options
+=("${daemon_name}-${inst}")
273 if check_daemon
$daemon_name; then
274 watchfrr_options
+=($daemon_name)
281 # Start if at least one daemon is activated.
282 if [ $found_one -eq 1 ]; then
283 echo -n "Starting Frr monitor daemon:"
292 echo -n "Stopping Frr monitor daemon:"
297 # Stops all daemons that have a lower level of priority than the given.
298 # (technically if daemon_prio >= wanted_prio)
307 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
308 daemon
=${BASH_REMATCH[1]}
309 inst
=${BASH_REMATCH[2]}
315 daemon_list
=${daemon:-$DAEMONS}
317 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
319 for prio_i
in `seq 10 -1 $wanted_prio`; do
320 for daemon_name
in $daemon_list; do
321 eval daemon_prio
=\
${${daemon_name}:0:3}
323 if [ $daemon_prio -eq $prio_i ]; then
324 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
325 if [ -n "$daemon_inst" ]; then
326 for i
in ${daemon_inst}; do
327 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
328 stop
"$daemon_name" "$inst"
329 elif [ x
"$inst" == x
]; then
330 stop
"$daemon_name" "$i"
341 if [ -z "$inst" ]; then
342 # Now stop other daemons that're prowling, coz the daemons file changed
343 echo -n "Stopping other frr daemons"
344 if [ -n "$daemon" ]; then
345 eval "file_list_suffix="$V_PATH"/"$daemon*""
347 eval "file_list_suffix="$V_PATH/*""
349 for pidfile
in $file_list_suffix.pid
; do
350 PID
=`cat $pidfile 2>/dev/null`
351 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
357 echo -n "Removing remaining .vty files"
358 for vtyfile
in $file_list_suffix.vty
; do
365 # Starts all daemons that have a higher level of priority than the given.
366 # (technically if daemon_prio <= wanted_prio)
376 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
377 daemon
=${BASH_REMATCH[1]}
378 inst
=${BASH_REMATCH[2]}
384 daemon_list
=${daemon:-$DAEMONS}
386 echo -n "Starting Frr daemons (prio:$wanted_prio):"
388 for prio_i
in `seq 1 $wanted_prio`; do
389 for daemon_name
in $daemon_list; do
390 eval daemon_prio
=\$
${daemon_name}
392 if [ $daemon_prio -eq $prio_i ]; then
393 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
394 if [ -n "$daemon_inst" ]; then
395 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
396 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
399 # Check if we're starting again by switching from single instance
401 if started
"$daemon_name"; then
402 PIDFILE
=`pidfile $daemon_name`
404 --stop --quiet --oknodo \
405 --pidfile "$PIDFILE" \
406 --exec "$D_PATH/$daemon_name"
412 for i
in ${daemon_inst}; do
413 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
414 start
"$daemon_name" "$inst"
415 elif [ x
"$inst" == x
]; then
416 start
"$daemon_name" "$i"
420 # Check if we're starting again by switching from
421 # single instance to MI version
422 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
423 for pidfile
in $file_list_suffix.pid
; do
424 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
428 for vtyfile
in $file_list_suffix.vty
; do
445 local failed_status
=0
447 if [ -n "$1" ] && [[ "$1" =~
(.
*)-(.
*) ]]; then
448 daemon
=${BASH_REMATCH[1]}
449 inst
=${BASH_REMATCH[2]}
454 daemon_list
=${daemon:-$DAEMONS}
456 # Which daemons have been started?
457 for daemon_name
in $daemon_list; do
458 eval daemon_prio
=\$
$daemon_name
459 if [ "$daemon_prio" -gt 0 ]; then
460 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
461 if [ -n "$daemon_inst" ]; then
462 for i
in ${daemon_inst}; do
463 if [ -n "$inst" -a "$inst" = "$i" ]; then
464 started
"$1" "log" || failed_status
=$?
465 elif [ -z "$inst" ]; then
466 started
"$daemon_name-$i" "log" || failed_status
=$?
470 started
"$daemon_name" "log" || failed_status
=$?
475 # All daemons that need to have been started are up and running
476 return $failed_status
479 #########################################################
481 #########################################################
483 # Config broken but script must exit silently.
484 [ ! -r "$C_PATH/daemons" ] && exit 0
488 .
"$C_PATH/debian.conf"
490 # Read configuration variable file if it is present
491 [ -r /etc
/default
/frr
] && .
/etc
/default
/frr
493 MAX_INSTANCES
=${MAX_INSTANCES:=5}
495 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
498 if [ ! -d $V_PATH ]; then
499 echo "Creating $V_PATH"
501 chown frr
:frr
$V_PATH
505 if [ -n "$3" ] && [ "$3" != "all" ]; then
507 elif [ -n "$2" ] && [ "$2" != "all" ]; then
513 # Try to load this necessary (at least for 2.6) module.
514 if [ -d /lib
/modules
/`uname -r` ] ; then
515 echo "Loading capability module if not yet done."
516 set +e
; LC_ALL
=C modprobe
-a capability
2>&1 |
egrep -v "(not found|Can't locate)"; set -e
521 if [ "$2" != "watchfrr" ]; then
528 1|
2|
3|
4|
5|
6|
7|
8|
9|
10)
529 # Stop/start daemons for the appropriate priority level
536 # Stop all daemons at level '0' or 'stop'
538 if [ "$dmn" != "watchfrr" ]; then
539 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
543 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
544 echo "Removing all routes made by FRR."
545 ip route flush proto bgp
546 ip route flush proto ospf
547 ip route flush proto static
548 ip route flush proto rip
549 ip route flush proto ripng
550 ip route flush proto zebra
551 ip route flush proto isis
554 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
560 # Just apply the commands that have changed, no restart necessary
561 [ ! -x "$RELOAD_SCRIPT" ] && echo "frr-reload script not available" && exit 0
562 NEW_CONFIG_FILE
="${2:-$C_PATH/frr.conf}"
563 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
564 echo "Applying only incremental changes to running configuration from frr.conf"
565 "$RELOAD_SCRIPT" --reload /etc
/frr
/frr.conf
574 restart|force-reload
)
581 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
582 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
583 echo " reload applies only modifications from the running config to all daemons."
584 echo " reload neither restarts starts any daemon nor starts any new ones."
585 echo " Read /usr/share/doc/frr/README.Debian for details."
590 echo "Exiting from the script"