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)"
155 --pidfile=`pidfile $1` \
156 --exec "$D_PATH/$1" \
158 `eval echo "$""$1""_options"`
162 # Stop the daemon given in the parameter, printing its name to the terminal.
173 if ! started
"$inst" ; then
177 PIDFILE
=`pidfile $inst`
178 PID
=`cat $PIDFILE 2>/dev/null`
179 ${SSD} --stop --quiet --retry=TERM
/30/KILL
/5 --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1"
181 # Now we have to wait until $DAEMON has _really_ stopped.
183 if test -n "$PID" && kill -0 $PID 2>/dev
/null
; then
184 echo -n " (waiting) ."
186 while kill -0 $PID 2>/dev
/null
; do
188 if [ $cnt -gt 60 ]; then
189 # Waited 120 secs now, fail.
198 rm -f `pidfile $inst`
199 rm -f `vtyfile $inst`
203 # Converts values from /etc/frr/daemons to all-numeric values.
204 convert_daemon_prios
()
206 for name
in $DAEMONS zebra vtysh_enable watchfrr_enable
; do
207 # First, assign the value set by the user to $value
208 eval value
=\
${${name}:0:3}
210 # Daemon not activated or entry missing?
211 if [ "$value" = "no" -o "$value" = "" ]; then value
=0; fi
213 # These strings parsed for backwards compatibility.
214 if [ "$value" = "yes" -o "$value" = "true" ]; then
218 # Zebra is threatened special. It must be between 0=off and the first
219 # user assigned value "1" so we increase all other enabled daemons' values.
220 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value
=`expr "$value" + 1`; fi
222 # If e.g. name is zebra then we set "zebra=yes".
227 # Starts watchfrr for all wanted daemons.
235 # Start the monitor daemon only if desired.
236 if [ 0 -eq "$watchfrr_enable" ]; then
240 # Check variable type
241 if ! declare -p watchfrr_options |
grep -q '^declare \-a'; then
243 echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!"
244 echo "ERROR: Please convert config file and restart!"
248 # Which daemons have been started?
250 for daemon_name
in $DAEMONS; do
251 eval daemon_prio
=\$
$daemon_name
252 if [ "$daemon_prio" -gt 0 ]; then
253 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
254 if [ -n "$daemon_inst" ]; then
255 for inst
in ${daemon_inst}; do
256 eval "inst_disable=\${${daemon_name}_${inst}}"
257 if [ -z ${inst_disable} ] ||
[ ${inst_disable} != 0 ]; then
258 if check_daemon
$daemon_name $inst; then
259 watchfrr_options
+=("${daemon_name}-${inst}")
264 if check_daemon
$daemon_name; then
265 watchfrr_options
+=($daemon_name)
272 # Start if at least one daemon is activated.
273 if [ $found_one -eq 1 ]; then
274 echo -n "Starting Frr monitor daemon:"
283 echo -n "Stopping Frr monitor daemon:"
288 # Stops all daemons that have a lower level of priority than the given.
289 # (technically if daemon_prio >= wanted_prio)
298 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
299 daemon
=${BASH_REMATCH[1]}
300 inst
=${BASH_REMATCH[2]}
306 daemon_list
=${daemon:-$DAEMONS}
308 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
310 for prio_i
in `seq 10 -1 $wanted_prio`; do
311 for daemon_name
in $daemon_list; do
312 eval daemon_prio
=\
${${daemon_name}:0:3}
314 if [ $daemon_prio -eq $prio_i ]; then
315 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
316 if [ -n "$daemon_inst" ]; then
317 for i
in ${daemon_inst}; do
318 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
319 stop
"$daemon_name" "$inst"
320 elif [ x
"$inst" == x
]; then
321 stop
"$daemon_name" "$i"
332 if [ -z "$inst" ]; then
333 # Now stop other daemons that're prowling, coz the daemons file changed
334 echo -n "Stopping other frr daemons"
335 if [ -n "$daemon" ]; then
336 eval "file_list_suffix="$V_PATH"/"$daemon*""
338 eval "file_list_suffix="$V_PATH/*""
340 for pidfile
in $file_list_suffix.pid
; do
341 PID
=`cat $pidfile 2>/dev/null`
342 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
348 echo -n "Removing remaining .vty files"
349 for vtyfile
in $file_list_suffix.vty
; do
356 # Starts all daemons that have a higher level of priority than the given.
357 # (technically if daemon_prio <= wanted_prio)
367 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
368 daemon
=${BASH_REMATCH[1]}
369 inst
=${BASH_REMATCH[2]}
375 daemon_list
=${daemon:-$DAEMONS}
377 echo -n "Starting Frr daemons (prio:$wanted_prio):"
379 for prio_i
in `seq 1 $wanted_prio`; do
380 for daemon_name
in $daemon_list; do
381 eval daemon_prio
=\$
${daemon_name}
383 if [ $daemon_prio -eq $prio_i ]; then
384 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
385 if [ -n "$daemon_inst" ]; then
386 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
387 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
390 # Check if we're starting again by switching from single instance
392 if started
"$daemon_name"; then
393 PIDFILE
=`pidfile $daemon_name`
395 --stop --quiet --oknodo \
396 --pidfile "$PIDFILE" \
397 --exec "$D_PATH/$daemon_name"
403 for i
in ${daemon_inst}; do
404 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
405 start
"$daemon_name" "$inst"
406 elif [ x
"$inst" == x
]; then
407 start
"$daemon_name" "$i"
411 # Check if we're starting again by switching from
412 # single instance to MI version
413 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
414 for pidfile
in $file_list_suffix.pid
; do
415 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
419 for vtyfile
in $file_list_suffix.vty
; do
436 local failed_status
=0
438 if [ -n "$1" ] && [[ "$1" =~
(.
*)-(.
*) ]]; then
439 daemon
=${BASH_REMATCH[1]}
440 inst
=${BASH_REMATCH[2]}
445 daemon_list
=${daemon:-$DAEMONS}
447 # Which daemons have been started?
448 for daemon_name
in $daemon_list; do
449 eval daemon_prio
=\$
$daemon_name
450 if [ "$daemon_prio" -gt 0 ]; then
451 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
452 if [ -n "$daemon_inst" ]; then
453 for i
in ${daemon_inst}; do
454 if [ -n "$inst" -a "$inst" = "$i" ]; then
455 started
"$1" "log" || failed_status
=$?
456 elif [ -z "$inst" ]; then
457 started
"$daemon_name-$i" "log" || failed_status
=$?
461 started
"$daemon_name" "log" || failed_status
=$?
466 # All daemons that need to have been started are up and running
467 return $failed_status
470 #########################################################
472 #########################################################
474 # Config broken but script must exit silently.
475 [ ! -r "$C_PATH/daemons" ] && exit 0
479 .
"$C_PATH/debian.conf"
481 # Read configuration variable file if it is present
482 [ -r /etc
/default
/frr
] && .
/etc
/default
/frr
484 MAX_INSTANCES
=${MAX_INSTANCES:=5}
486 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
489 if [ ! -d $V_PATH ]; then
490 echo "Creating $V_PATH"
492 chown frr
:frr
$V_PATH
496 if [ -n "$3" ] && [ "$3" != "all" ]; then
498 elif [ -n "$2" ] && [ "$2" != "all" ]; then
504 # Try to load this necessary (at least for 2.6) module.
505 if [ -d /lib
/modules
/`uname -r` ] ; then
506 echo "Loading capability module if not yet done."
507 set +e
; LC_ALL
=C modprobe
-a capability
2>&1 |
egrep -v "(not found|Can't locate)"; set -e
512 if [ "$2" != "watchfrr" ]; then
519 1|
2|
3|
4|
5|
6|
7|
8|
9|
10)
520 # Stop/start daemons for the appropriate priority level
527 # Stop all daemons at level '0' or 'stop'
529 if [ "$dmn" != "watchfrr" ]; then
530 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
534 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
535 echo "Removing all routes made by FRR."
536 ip route flush proto bgp
537 ip route flush proto ospf
538 ip route flush proto static
539 ip route flush proto rip
540 ip route flush proto ripng
541 ip route flush proto zebra
542 ip route flush proto isis
545 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
551 # Just apply the commands that have changed, no restart necessary
552 [ ! -x "$RELOAD_SCRIPT" ] && echo "frr-reload script not available" && exit 0
553 NEW_CONFIG_FILE
="${2:-$C_PATH/frr.conf}"
554 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
555 echo "Applying only incremental changes to running configuration from frr.conf"
556 "$RELOAD_SCRIPT" --reload /etc
/frr
/frr.conf
565 restart|force-reload
)
572 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
573 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
574 echo " reload applies only modifications from the running config to all daemons."
575 echo " reload neither restarts starts any daemon nor starts any new ones."
576 echo " Read /usr/share/doc/frr/README.Debian for details."
581 echo "Exiting from the script"