]> git.proxmox.com Git - mirror_frr.git/blame - tools/frr.in
debianpkg, tools: Add fabricd to distribution scripts
[mirror_frr.git] / tools / frr.in
CommitLineData
df44cf00 1#!/bin/bash
651415bd
DS
2#
3### BEGIN INIT INFO
d8e4c438 4# Provides: frr
651415bd
DS
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
8# Default-Stop: 0 1 6
d8e4c438
DS
9# Short-Description: start and stop the Frr routing suite
10# Description: Frr is a routing suite for IP routing protocols like
651415bd 11# BGP, OSPF, RIP and others. This script contols the main
d8e4c438 12# daemon "frr" as well as the individual protocol daemons.
651415bd
DS
13### END INIT INFO
14#
df44cf00 15
651415bd 16PATH=/bin:/usr/bin:/sbin:/usr/sbin
40da52d8
DL
17D_PATH="@CFG_SBIN@" # /usr/lib/frr
18C_PATH="@CFG_SYSCONF@" # /etc/frr
19V_PATH="@CFG_STATE@" # /var/run/frr
20VTYSH="@vtysh_bin@" # /usr/bin/vtysh
21FRR_USER="@enable_user@" # frr
22FRR_GROUP="@enable_group@" # frr
23FRR_VTY_GROUP="@enable_vty_group@" # frrvty
651415bd 24
d8e4c438
DS
25# Local Daemon selection may be done by using /etc/frr/daemons.
26# See /usr/share/doc/frr/README.Debian.gz for further information.
9473e340 27# Keep zebra first and do not list watchfrr!
bf8e16b5 28DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd"
651415bd 29MAX_INSTANCES=5
40da52d8 30RELOAD_SCRIPT="$D_PATH/frr-reload.py"
651415bd 31
915c81b3 32if [ -e /lib/lsb/init-functions ]; then
25e87a8f 33 . /lib/lsb/init-functions
915c81b3 34fi
651415bd 35
40da52d8 36if [ -f $D_PATH/ssd ]; then
25e87a8f 37 SSD=$D_PATH/ssd
d84fd25b 38else
25e87a8f 39 SSD=`which start-stop-daemon`
d84fd25b
DS
40fi
41
651415bd
DS
42# Print the name of the pidfile.
43pidfile()
44{
25e87a8f 45 echo "$V_PATH/$1.pid"
651415bd
DS
46}
47
48# Print the name of the vtysh.
49vtyfile()
50{
25e87a8f 51 echo "$V_PATH/$1.vty"
651415bd
DS
52}
53
40da52d8
DL
54chownfrr()
55{
25e87a8f
QY
56 test -n "$FRR_USER" && chown "$FRR_USER" "$1"
57 test -n "$FRR_GROUP" && chgrp "$FRR_GROUP" "$1"
40da52d8
DL
58}
59
651415bd
DS
60# Check if daemon is started by using the pidfile.
61started()
62{
25e87a8f
QY
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 $?
66 else
67 kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1
68 return 0
69 fi
651415bd
DS
70}
71
72# Loads the config via vtysh -b if configured to do so.
73vtysh_b ()
74{
25e87a8f
QY
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
77 $VTYSH -b -n
78 fi
651415bd
DS
79}
80
81# Check if the daemon is activated and if its executable and config files
82# are in place.
83# params: daemon name
84# returns: 0=ok, 1=error
85check_daemon()
86{
25e87a8f
QY
87 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
88 # check for daemon binary
89 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
90 fi
91
92 # If the integrated config file is used the others are not checked.
93 if [ -r "$C_PATH/frr.conf" ]; then
94 return 0
95 fi
96
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
101 if [ -n "$2" ]; then
102 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
103 touch "$C_PATH/$1-$2.conf"
104 chownfrr "$C_PATH/$1-$2.conf"
105 fi
106 elif [ ! -r "$C_PATH/$1.conf" ]; then
107 touch "$C_PATH/$1.conf"
108 chownfrr "$C_PATH/$1.conf"
109 fi
110 fi
111 return 0
651415bd
DS
112}
113
114# Starts the server if it's not alrady running according to the pid file.
d8e4c438 115# The Frr daemons creates the pidfile when starting.
651415bd 116start()
df44cf00 117{
25e87a8f
QY
118 ulimit -n $MAX_FDS
119 if [ "$1" = "watchfrr" ]; then
120
121 # We may need to restart watchfrr if new daemons are added and/or
122 # removed
123 if started "$1" ; then
124 stop watchfrr
125 else
126 # Echo only once. watchfrr is printed in the stop above
127 echo -n " $1"
128 fi
129
130 ${SSD} \
131 --start \
132 --pidfile=`pidfile $1` \
133 --exec "$D_PATH/$1" \
134 -- \
135 "${watchfrr_options[@]}"
136
137 elif [ -n "$2" ]; then
138 echo -n " $1-$2"
139 if ! check_daemon $1 $2 ; then
140 echo -n " (binary does not exist)"
141 return;
142 fi
143
144 ${SSD} \
145 --start \
146 --pidfile=`pidfile $1-$2` \
147 --exec "$D_PATH/$1" \
148 -- \
149 `eval echo "$""$1""_options"` -n "$2"
150 else
151 echo -n " $1"
152 if ! check_daemon $1; then
153 echo -n " (binary does not exist)"
154 return;
155 fi
156
157 if [ "$valgrind_enable" = "yes" ]; then
158 ${SSD} \
159 --start \
160 --pidfile=`pidfile $1` \
161 --exec "$valgrind" \
162 -- --trace-children=no --leak-check=full --log-file=/var/log/frr/$1-valgrind.log $D_PATH/$1 \
163 `eval echo "$""$1""_options"`
164 else
165 ${SSD} \
166 --start \
167 --pidfile=`pidfile $1` \
168 --exec "$D_PATH/$1" \
169 -- \
170 `eval echo "$""$1""_options"`
171 fi
172 fi
7ac1de8e
DS
173
174 # Start the staticd automatically
175 if [ "$1" = "zebra" ]; then
25e87a8f
QY
176 echo -n "starting staticd since zebra is running"
177 if ! check_daemon staticd ; then
178 echo -n " (binary does not exist)"
179 return;
180 fi
181
182 ${SSD} \
183 --start \
184 --pidfile=`pidfile staticd` \
185 --exec "$D_PATH/staticd" \
186 -- \
187 `eval echo "$"staticd"_options"`
7ac1de8e 188 fi
651415bd
DS
189}
190
191# Stop the daemon given in the parameter, printing its name to the terminal.
192stop()
193{
25e87a8f 194 local inst
7ac1de8e 195
25e87a8f
QY
196 if [ -n "$2" ]; then
197 inst="$1-$2"
198 else
199 inst="$1"
200 fi
201
202 if ! started "$inst" ; then
203 echo -n " ($inst)"
204 return 0
205 else
206 PIDFILE=`pidfile $inst`
207 PID=`cat $PIDFILE 2>/dev/null`
208 kill -2 $PID 2>/dev/null
209 #
210 # Now we have to wait until $DAEMON has _really_ stopped.
211 #
212 if test -n "$PID" && kill -0 $PID 2>/dev/null; then
213 echo -n " (waiting) ."
214 cnt=0
215 while kill -0 $PID 2>/dev/null; do
216 cnt=`expr $cnt + 1`
217 if [ $cnt -gt 60 ]; then
218 # Waited 120 secs now, fail.
219 echo -n "Failed.. "
220 break
221 fi
222 sleep 2
223 echo -n "."
224 done
225 fi
226 echo -n " $inst"
227 rm -f `pidfile $inst`
228 rm -f `vtyfile $inst`
229
230 if [ "$1" = "zebra" ]; then
231 echo -n "Stopping staticd since zebra is running"
232 stop staticd
233 fi
7ac1de8e 234 fi
df44cf00 235}
236
d8e4c438 237# Converts values from /etc/frr/daemons to all-numeric values.
651415bd 238convert_daemon_prios()
df44cf00 239{
25e87a8f
QY
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}
651415bd 243
25e87a8f
QY
244 # Daemon not activated or entry missing?
245 if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
651415bd 246
25e87a8f
QY
247 # These strings parsed for backwards compatibility.
248 if [ "$value" = "yes" -o "$value" = "true" ]; then
249 value=1;
250 fi
651415bd 251
25e87a8f
QY
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
651415bd 255
25e87a8f
QY
256 # If e.g. name is zebra then we set "zebra=yes".
257 eval $name=$value
258 done
df44cf00 259}
260
9473e340
DS
261# Starts watchfrr for all wanted daemons.
262start_watchfrr()
df44cf00 263{
25e87a8f
QY
264 local daemon_name
265 local daemon_prio
266 local found_one
267 local daemon_inst
268
269 # Start the monitor daemon only if desired.
270 if [ 0 -eq "$watchfrr_enable" ]; then
271 return
272 fi
273
274 # Check variable type
275 if ! declare -p watchfrr_options | grep -q '^declare \-a'; then
276 echo
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!"
279 exit 1
280 fi
281
282 # Which daemons have been started?
283 found_one=0
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}")
294 fi
295 fi
296 done
297 else
298 if check_daemon $daemon_name; then
299 watchfrr_options+=($daemon_name)
300 fi
301 fi
302 found_one=1
303 fi
304 done
305
306 # Start if at least one daemon is activated.
307 if [ $found_one -eq 1 ]; then
308 echo -n "Starting Frr monitor daemon:"
309 start watchfrr
310 echo "."
311 fi
df44cf00 312}
313
9473e340
DS
314# Stopps watchfrr.
315stop_watchfrr()
df44cf00 316{
25e87a8f
QY
317 echo -n "Stopping Frr monitor daemon:"
318 stop watchfrr
319 echo "."
651415bd
DS
320}
321
322# Stops all daemons that have a lower level of priority than the given.
323# (technically if daemon_prio >= wanted_prio)
324stop_prio()
325{
25e87a8f
QY
326 local wanted_prio
327 local daemon_prio
328 local daemon_list
329 local daemon_inst
330 local inst
331
332 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
333 daemon=${BASH_REMATCH[1]}
334 inst=${BASH_REMATCH[2]}
335 else
336 daemon="$2"
337 fi
338
339 wanted_prio=$1
340 daemon_list=${daemon:-$DAEMONS}
341
342 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
343
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}
347 daemon_inst=""
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"
356 fi
357 done
358 else
359 stop "$daemon_name"
360 fi
361 fi
362 done
363 done
364
365 echo "."
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*""
371 else
372 eval "file_list_suffix="$V_PATH/*""
373 fi
374 for pidfile in $file_list_suffix.pid; do
375 PID=`cat $pidfile 2>/dev/null`
376 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
377 echo -n "."
378 rm -rf "$pidfile"
379 done
380 echo "."
381
382 echo -n "Removing remaining .vty files"
383 for vtyfile in $file_list_suffix.vty; do
384 rm -rf "$vtyfile"
385 done
386 echo "."
387 fi
651415bd
DS
388}
389
390# Starts all daemons that have a higher level of priority than the given.
391# (technically if daemon_prio <= wanted_prio)
392start_prio()
393{
25e87a8f
QY
394 local wanted_prio
395 local daemon_prio
396 local daemon_list
397 local daemon_name
398 local daemon_inst
399 local inst
400
401 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
402 daemon=${BASH_REMATCH[1]}
403 inst=${BASH_REMATCH[2]}
404 else
405 daemon="$2"
406 fi
407
408 wanted_prio=$1
409 daemon_list=${daemon:-$DAEMONS}
410
411 echo -n "Starting Frr daemons (prio:$wanted_prio):"
412
413 for prio_i in `seq 1 $wanted_prio`; do
414 for daemon_name in $daemon_list; do
415 eval daemon_prio=\$${daemon_name}
416 daemon_inst=""
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"
422 exit 1
423 fi
424 # Check if we're starting again by switching from single instance
425 # to MI version
426 if started "$daemon_name"; then
427 PIDFILE=`pidfile $daemon_name`
428 ${SSD} \
429 --stop --quiet --oknodo \
430 --pidfile "$PIDFILE" \
431 --exec "$D_PATH/$daemon_name"
432
433 rm -f `pidfile $1`
434 rm -f `vtyfile $1`
435 fi
436
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"
442 fi
443 done
444 else
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"
450 echo -n "."
451 rm -rf "$pidfile"
452 done
453 for vtyfile in $file_list_suffix.vty; do
454 rm -rf "$vtyfile"
455 done
456
457 start "$daemon_name"
458 fi
459 fi
460 done
461 done
462 echo "."
df44cf00 463}
464
651415bd 465check_status()
df44cf00 466{
25e87a8f
QY
467 local daemon_name
468 local daemon_prio
469 local daemon_inst
470 local failed_status=0
471
472 if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
473 daemon=${BASH_REMATCH[1]}
474 inst=${BASH_REMATCH[2]}
475 else
476 daemon="$1"
477 fi
478
479 daemon_list=${daemon:-$DAEMONS}
480
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=$?
492 fi
493 done
494 else
495 started "$daemon_name" "log" || failed_status=$?
496 fi
497 fi
498 done
499
500 # All daemons that need to have been started are up and running
501 return $failed_status
df44cf00 502}
503
651415bd
DS
504#########################################################
505# Main program #
506#########################################################
507
508# Config broken but script must exit silently.
509[ ! -r "$C_PATH/daemons" ] && exit 0
510
511# Load configuration
512. "$C_PATH/daemons"
82e6e358 513. "$C_PATH/daemons.conf"
651415bd
DS
514
515# Read configuration variable file if it is present
d8e4c438 516[ -r /etc/default/frr ] && . /etc/default/frr
651415bd
DS
517
518MAX_INSTANCES=${MAX_INSTANCES:=5}
519
520# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
521convert_daemon_prios
522
523if [ ! -d $V_PATH ]; then
25e87a8f
QY
524 echo "Creating $V_PATH"
525 mkdir -p $V_PATH
526 chownfrr $V_PATH
527 chmod 755 /$V_PATH
651415bd
DS
528fi
529
530if [ -n "$3" ] && [ "$3" != "all" ]; then
25e87a8f 531 dmn="$2"-"$3"
651415bd 532elif [ -n "$2" ] && [ "$2" != "all" ]; then
25e87a8f 533 dmn="$2"
651415bd
DS
534fi
535
df44cf00 536case "$1" in
25e87a8f
QY
537 start)
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
542 fi
543
544 # Start all daemons
545 cd $C_PATH/
546 if [ "$2" != "watchfrr" ]; then
547 start_prio 10 $dmn
548 fi
549 start_watchfrr
550 vtysh_b
551 ;;
552
553 1|2|3|4|5|6|7|8|9|10)
554 # Stop/start daemons for the appropriate priority level
555 stop_prio $1
556 start_prio $1
557 vtysh_b
558 ;;
559
560 stop|0)
561 # Stop all daemons at level '0' or 'stop'
562 stop_watchfrr
563 if [ "$dmn" != "watchfrr" ]; then
564 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
565 stop_prio 0 $dmn
566 fi
567
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
590 ip route flush proto 197
591 else
592 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
593 start_watchfrr
594 fi
595 ;;
596
597 reload)
598 # Just apply the commands that have changed, no restart necessary
599 if [ ! -x "$RELOAD_SCRIPT" ]; then
600 echo "Please install frr-pythontools package. Required for reload"
601 exit 0
602 fi
603
604 NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}"
605 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
606 echo "Applying only incremental changes to running configuration from frr.conf"
607 "$RELOAD_SCRIPT" --reload $C_PATH/frr.conf
608 exit $?
609 ;;
610
611 status)
612 check_status $dmn
613 exit $?
614 ;;
615
616 restart|force-reload)
617 $0 stop $dmn
618 sleep 1
619 $0 start $dmn
620 ;;
621
622 *)
623 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
624 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
625 echo " reload applies only modifications from the running config to all daemons."
626 echo " reload neither restarts starts any daemon nor starts any new ones."
627 echo " Read /usr/share/doc/frr/README.Debian for details."
628 exit 1
629 ;;
df44cf00 630esac
631
651415bd 632echo "Exiting from the script"
df44cf00 633exit 0