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 fabricd vrrpd"
30 RELOAD_SCRIPT
="$D_PATH/frr-reload.py"
32 if [ -e /lib
/lsb
/init-functions
]; then
33 .
/lib
/lsb
/init-functions
36 if [ -f $D_PATH/ssd
]; then
39 SSD
=`which start-stop-daemon`
42 # Print the name of the pidfile.
48 # Print the name of the vtysh.
56 test -n "$FRR_USER" && chown
"$FRR_USER" "$1"
57 test -n "$FRR_GROUP" && chgrp
"$FRR_GROUP" "$1"
60 # Check if daemon is started by using the pidfile.
63 [ ! -e `pidfile $1` ] && return 3
64 if [ -n "$2" ] && [ "$2" == "log" ]; then
65 status_of_proc
-p `pidfile $1` $1 $1 && return 0 ||
return $?
67 kill -0 `cat \`pidfile
$1\
`` 2> /dev
/null ||
return 1
72 # Loads the config via vtysh -b if configured to do so.
75 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
76 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf
]; then
81 # Check if the daemon is activated and if its executable and config files
84 # returns: 0=ok, 1=error
87 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
88 # check for daemon binary
89 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
92 # If the integrated config file is used the others are not checked.
93 if [ -r "$C_PATH/frr.conf" ]; then
97 # vtysh_enable has no config file nor binary so skip check.
98 # (Not sure why vtysh_enable is in this list but does not hurt)
99 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
100 # check for config file
102 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
103 touch "$C_PATH/$1-$2.conf"
104 chownfrr
"$C_PATH/$1-$2.conf"
106 elif [ ! -r "$C_PATH/$1.conf" ]; then
107 touch "$C_PATH/$1.conf"
108 chownfrr
"$C_PATH/$1.conf"
114 # Starts the server if it's not alrady running according to the pid file.
115 # The Frr daemons creates the pidfile when starting.
122 ulimit -n $MAX_FDS > /dev
/null
2> /dev
/null
123 if [ "$dmn" = "watchfrr" ]; then
125 # We may need to restart watchfrr if new daemons are added and/or
127 if started
"$dmn" ; then
130 # Echo only once. watchfrr is printed in the stop above
134 eval "set - $watchfrr_options"
137 --pidfile=`pidfile $dmn` \
138 --exec "$D_PATH/$dmn" \
142 elif [ -n "$inst" ]; then
143 echo -n " $dmn-$inst"
144 if ! check_daemon
$dmn $inst ; then
145 echo -n " (binary does not exist)"
151 --pidfile=`pidfile $dmn-$inst` \
152 --exec "$D_PATH/$dmn" \
154 `eval echo "$""$dmn""_options"` -n "$inst"
156 if ! check_daemon
$dmn; then
157 echo -n " (binary does not exist)"
161 if [ "$valgrind_enable" = "yes" ]; then
164 --pidfile=`pidfile $dmn` \
166 -- --trace-children=no
--leak-check=full
--log-file=/var
/log
/frr
/$dmn-valgrind.log
$D_PATH/$dmn \
167 `eval echo "$""$dmn""_options"`
171 --pidfile=`pidfile $dmn` \
172 --exec "$D_PATH/$dmn" \
174 `eval echo "$""$dmn""_options"`
178 # Start the staticd automatically
179 if [ "$dmn" = "zebra" ]; then
180 echo -n "starting staticd since zebra is running"
181 if ! check_daemon staticd
; then
182 echo -n " (binary does not exist)"
188 --pidfile=`pidfile staticd` \
189 --exec "$D_PATH/staticd" \
191 `eval echo "$"staticd"_options"`
195 # Stop the daemon given in the parameter, printing its name to the terminal.
206 if ! started
"$inst" ; then
210 PIDFILE
=`pidfile $inst`
211 PID
=`cat $PIDFILE 2>/dev/null`
212 kill -2 $PID 2>/dev
/null
214 # Now we have to wait until $DAEMON has _really_ stopped.
216 if test -n "$PID" && kill -0 $PID 2>/dev
/null
; then
218 while kill -0 $PID 2>/dev
/null
; do
220 if [ $cnt -gt 60 ]; then
221 # Waited 120 secs now, fail.
228 rm -f `pidfile $inst`
229 rm -f `vtyfile $inst`
231 if [ "$1" = "zebra" ]; then
232 echo -n "Stopping staticd since zebra is running"
238 # Converts values from /etc/frr/daemons to all-numeric values.
239 convert_daemon_prios
()
241 for name
in $DAEMONS zebra vtysh_enable watchfrr_enable
; do
242 # First, assign the value set by the user to $value
243 eval value
=\
${${name}:0:3}
245 # Daemon not activated or entry missing?
246 if [ "$value" = "no" -o "$value" = "" ]; then value
=0; fi
248 # These strings parsed for backwards compatibility.
249 if [ "$value" = "yes" -o "$value" = "true" ]; then
253 # Zebra is threatened special. It must be between 0=off and the first
254 # user assigned value "1" so we increase all other enabled daemons' values.
255 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value
=`expr "$value" + 1`; fi
257 # If e.g. name is zebra then we set "zebra=yes".
262 # Starts watchfrr for all wanted daemons.
270 # Start the monitor daemon only if desired.
271 if [ 0 -eq "$watchfrr_enable" ]; then
275 # Check variable type
276 if declare -p watchfrr_options |
grep -q '^declare \-a'; then
278 watchfrr_options
="${watchfrr_options[@]}"
281 # Which daemons have been started?
283 for daemon_name
in $DAEMONS; do
284 eval daemon_prio
=\$
$daemon_name
285 if [ "$daemon_prio" -gt 0 ]; then
286 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
287 if [ -n "$daemon_inst" ]; then
288 for inst
in ${daemon_inst}; do
289 eval "inst_disable=\${${daemon_name}_${inst}}"
290 if [ -z ${inst_disable} ] ||
[ ${inst_disable} != 0 ]; then
291 if check_daemon
$daemon_name $inst; then
292 watchfrr_options
="$watchfrr_options ${daemon_name}-${inst}"
297 if check_daemon
$daemon_name; then
298 watchfrr_options
="$watchfrr_options $daemon_name"
305 # Start if at least one daemon is activated.
306 if [ $found_one -eq 1 ]; then
315 echo -n "Stopping Frr monitor daemon:"
320 # Stops all daemons that have a lower level of priority than the given.
321 # (technically if daemon_prio >= wanted_prio)
330 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
331 daemon
=${BASH_REMATCH[1]}
332 inst
=${BASH_REMATCH[2]}
338 daemon_list
=${daemon:-$DAEMONS}
340 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
342 for prio_i
in `seq 10 -1 $wanted_prio`; do
343 for daemon_name
in $daemon_list; do
344 eval daemon_prio
=\
${${daemon_name}:0:3}
346 if [ $daemon_prio -eq $prio_i ]; then
347 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
348 if [ -n "$daemon_inst" ]; then
349 for i
in ${daemon_inst}; do
350 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
351 stop
"$daemon_name" "$inst"
352 elif [ x
"$inst" == x
]; then
353 stop
"$daemon_name" "$i"
364 if [ -z "$inst" ]; then
365 # Now stop other daemons that're prowling, coz the daemons file changed
366 echo -n "Stopping other frr daemons"
367 if [ -n "$daemon" ]; then
368 eval "file_list_suffix="$V_PATH"/"$daemon*""
370 eval "file_list_suffix="$V_PATH/*""
372 for pidfile
in $file_list_suffix.pid
; do
373 PID
=`cat $pidfile 2>/dev/null`
374 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
380 echo -n "Removing remaining .vty files"
381 for vtyfile
in $file_list_suffix.vty
; do
388 # Starts all daemons that have a higher level of priority than the given.
389 # (technically if daemon_prio <= wanted_prio)
399 if [ -n "$2" ] && [[ "$2" =~
(.
*)-(.
*) ]]; then
400 daemon
=${BASH_REMATCH[1]}
401 inst
=${BASH_REMATCH[2]}
407 daemon_list
=${daemon:-$DAEMONS}
409 for prio_i
in `seq 1 $wanted_prio`; do
410 for daemon_name
in $daemon_list; do
411 eval daemon_prio
=\$
${daemon_name}
413 if [ $daemon_prio -eq $prio_i ]; then
414 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
415 if [ -n "$daemon_inst" ]; then
416 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
417 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
420 # Check if we're starting again by switching from single instance
422 if started
"$daemon_name"; then
423 PIDFILE
=`pidfile $daemon_name`
425 --stop --quiet --oknodo \
426 --pidfile "$PIDFILE" \
427 --exec "$D_PATH/$daemon_name"
433 for i
in ${daemon_inst}; do
434 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
435 start
"$daemon_name" "$inst"
436 elif [ x
"$inst" == x
]; then
437 start
"$daemon_name" "$i"
441 # Check if we're starting again by switching from
442 # single instance to MI version
443 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
444 for pidfile
in $file_list_suffix.pid
; do
445 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
448 for vtyfile
in $file_list_suffix.vty
; do
464 local failed_status
=0
466 if [ -n "$1" ] && [[ "$1" =~
(.
*)-(.
*) ]]; then
467 daemon
=${BASH_REMATCH[1]}
468 inst
=${BASH_REMATCH[2]}
473 daemon_list
=${daemon:-$DAEMONS}
475 # Which daemons have been started?
476 for daemon_name
in $daemon_list; do
477 eval daemon_prio
=\$
$daemon_name
478 if [ "$daemon_prio" -gt 0 ]; then
479 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
480 if [ -n "$daemon_inst" ]; then
481 for i
in ${daemon_inst}; do
482 if [ -n "$inst" -a "$inst" = "$i" ]; then
483 started
"$1" "log" || failed_status
=$?
484 elif [ -z "$inst" ]; then
485 started
"$daemon_name-$i" "log" || failed_status
=$?
489 started
"$daemon_name" "log" || failed_status
=$?
494 # All daemons that need to have been started are up and running
495 return $failed_status
498 #########################################################
500 #########################################################
502 # Config broken but script must exit silently.
503 [ ! -r "$C_PATH/daemons" ] && exit 0
507 if [ -e "$C_PATH/daemons.conf" ]; then
508 .
"$C_PATH/daemons.conf"
511 # Read configuration variable file if it is present
512 [ -r /etc
/default
/frr
] && .
/etc
/default
/frr
514 MAX_INSTANCES
=${MAX_INSTANCES:=5}
516 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
519 if [ ! -d $V_PATH ]; then
520 echo "Creating $V_PATH"
526 if [ -n "$3" ] && [ "$3" != "all" ]; then
528 elif [ -n "$2" ] && [ "$2" != "all" ]; then
534 # Try to load this necessary (at least for 2.6) module.
535 if [ -d /lib
/modules
/`uname -r` ] ; then
536 echo "Loading capability module if not yet done."
537 set +e
; LC_ALL
=C modprobe
-a capability
2>&1 |
egrep -v "(not found|Can't locate)"; set -e
542 if [ "$2" != "watchfrr" ]; then
549 1|
2|
3|
4|
5|
6|
7|
8|
9|
10)
550 # Stop/start daemons for the appropriate priority level
557 # Stop all daemons at level '0' or 'stop'
559 if [ "$dmn" != "watchfrr" ]; then
560 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
564 if [ -n "$dmn" -a "$dmn" != "zebra" ]; then
565 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
571 # Just apply the commands that have changed, no restart necessary
572 if [ ! -x "$RELOAD_SCRIPT" ]; then
573 echo "Please install frr-pythontools package. Required for reload"
577 NEW_CONFIG_FILE
="${2:-$C_PATH/frr.conf}"
578 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
579 echo "Applying only incremental changes to running configuration from frr.conf"
580 "$RELOAD_SCRIPT" --reload $C_PATH/frr.conf
589 restart|force-reload
)
596 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
597 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
598 echo " reload applies only modifications from the running config to all daemons."
599 echo " reload neither restarts starts any daemon nor starts any new ones."
600 echo " Read /usr/share/doc/frr/README.Debian for details."
605 echo "Exiting from the script"