]> git.proxmox.com Git - mirror_frr.git/blame - tools/frr.in
pathd: New SR-TE policy management daemon
[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
5c906377 24FRR_CONFIG_MODE="@enable_configfile_mask@" # 0600
68495906 25FRR_DEFAULT_PROFILE="@DFLT_NAME@" # traditional / datacenter
651415bd 26
d8e4c438
DS
27# Local Daemon selection may be done by using /etc/frr/daemons.
28# See /usr/share/doc/frr/README.Debian.gz for further information.
9473e340 29# Keep zebra first and do not list watchfrr!
4d7b695d 30DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd pathd"
651415bd 31MAX_INSTANCES=5
40da52d8 32RELOAD_SCRIPT="$D_PATH/frr-reload.py"
651415bd 33
915c81b3 34if [ -e /lib/lsb/init-functions ]; then
25e87a8f 35 . /lib/lsb/init-functions
915c81b3 36fi
651415bd 37
40da52d8 38if [ -f $D_PATH/ssd ]; then
25e87a8f 39 SSD=$D_PATH/ssd
d84fd25b 40else
25e87a8f 41 SSD=`which start-stop-daemon`
d84fd25b
DS
42fi
43
651415bd
DS
44# Print the name of the pidfile.
45pidfile()
46{
25e87a8f 47 echo "$V_PATH/$1.pid"
651415bd
DS
48}
49
50# Print the name of the vtysh.
51vtyfile()
52{
25e87a8f 53 echo "$V_PATH/$1.vty"
651415bd
DS
54}
55
40da52d8
DL
56chownfrr()
57{
25e87a8f
QY
58 test -n "$FRR_USER" && chown "$FRR_USER" "$1"
59 test -n "$FRR_GROUP" && chgrp "$FRR_GROUP" "$1"
5c906377 60 test -n "$FRR_CONFIG_MODE" && chmod "$FRR_CONFIG_MODE" "$1"
40da52d8
DL
61}
62
651415bd
DS
63# Check if daemon is started by using the pidfile.
64started()
65{
25e87a8f
QY
66 [ ! -e `pidfile $1` ] && return 3
67 if [ -n "$2" ] && [ "$2" == "log" ]; then
68 status_of_proc -p `pidfile $1` $1 $1 && return 0 || return $?
69 else
70 kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1
71 return 0
72 fi
651415bd
DS
73}
74
75# Loads the config via vtysh -b if configured to do so.
76vtysh_b ()
77{
25e87a8f
QY
78 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
79 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf ]; then
e220f954 80 $VTYSH -b
25e87a8f 81 fi
651415bd
DS
82}
83
84# Check if the daemon is activated and if its executable and config files
85# are in place.
86# params: daemon name
87# returns: 0=ok, 1=error
88check_daemon()
89{
25e87a8f
QY
90 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
91 # check for daemon binary
92 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
93 fi
94
95 # If the integrated config file is used the others are not checked.
96 if [ -r "$C_PATH/frr.conf" ]; then
97 return 0
98 fi
99
100 # vtysh_enable has no config file nor binary so skip check.
101 # (Not sure why vtysh_enable is in this list but does not hurt)
102 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
103 # check for config file
104 if [ -n "$2" ]; then
105 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
106 touch "$C_PATH/$1-$2.conf"
107 chownfrr "$C_PATH/$1-$2.conf"
108 fi
109 elif [ ! -r "$C_PATH/$1.conf" ]; then
110 touch "$C_PATH/$1.conf"
111 chownfrr "$C_PATH/$1.conf"
112 fi
113 fi
114 return 0
651415bd
DS
115}
116
117# Starts the server if it's not alrady running according to the pid file.
d8e4c438 118# The Frr daemons creates the pidfile when starting.
651415bd 119start()
df44cf00 120{
10ea85ee
DL
121 local dmn inst
122 dmn="$1"
123 inst="$2"
124
125 ulimit -n $MAX_FDS > /dev/null 2> /dev/null
126 if [ "$dmn" = "watchfrr" ]; then
25e87a8f
QY
127
128 # We may need to restart watchfrr if new daemons are added and/or
129 # removed
10ea85ee 130 if started "$dmn" ; then
25e87a8f
QY
131 stop watchfrr
132 else
133 # Echo only once. watchfrr is printed in the stop above
10ea85ee 134 echo -n " $dmn"
25e87a8f
QY
135 fi
136
10ea85ee 137 eval "set - $watchfrr_options"
25e87a8f
QY
138 ${SSD} \
139 --start \
10ea85ee
DL
140 --pidfile=`pidfile $dmn` \
141 --exec "$D_PATH/$dmn" \
25e87a8f 142 -- \
10ea85ee 143 "$@"
25e87a8f 144
10ea85ee
DL
145 elif [ -n "$inst" ]; then
146 echo -n " $dmn-$inst"
147 if ! check_daemon $dmn $inst ; then
25e87a8f
QY
148 echo -n " (binary does not exist)"
149 return;
150 fi
151
152 ${SSD} \
153 --start \
10ea85ee
DL
154 --pidfile=`pidfile $dmn-$inst` \
155 --exec "$D_PATH/$dmn" \
25e87a8f 156 -- \
68495906 157 `eval echo "$""$dmn""_options"` $frr_global_options -n "$inst"
25e87a8f 158 else
10ea85ee 159 if ! check_daemon $dmn; then
25e87a8f
QY
160 echo -n " (binary does not exist)"
161 return;
162 fi
163
164 if [ "$valgrind_enable" = "yes" ]; then
165 ${SSD} \
166 --start \
10ea85ee 167 --pidfile=`pidfile $dmn` \
25e87a8f 168 --exec "$valgrind" \
10ea85ee 169 -- --trace-children=no --leak-check=full --log-file=/var/log/frr/$dmn-valgrind.log $D_PATH/$dmn \
68495906 170 `eval echo "$""$dmn""_options"` $frr_global_options
25e87a8f
QY
171 else
172 ${SSD} \
173 --start \
10ea85ee
DL
174 --pidfile=`pidfile $dmn` \
175 --exec "$D_PATH/$dmn" \
25e87a8f 176 -- \
68495906 177 `eval echo "$""$dmn""_options"` $frr_global_options
25e87a8f
QY
178 fi
179 fi
7ac1de8e
DS
180
181 # Start the staticd automatically
10ea85ee 182 if [ "$dmn" = "zebra" ]; then
25e87a8f
QY
183 echo -n "starting staticd since zebra is running"
184 if ! check_daemon staticd ; then
185 echo -n " (binary does not exist)"
186 return;
187 fi
188
189 ${SSD} \
190 --start \
191 --pidfile=`pidfile staticd` \
192 --exec "$D_PATH/staticd" \
193 -- \
68495906 194 `eval echo "$"staticd"_options"` $frr_global_options
7ac1de8e 195 fi
651415bd
DS
196}
197
198# Stop the daemon given in the parameter, printing its name to the terminal.
199stop()
200{
25e87a8f 201 local inst
7ac1de8e 202
25e87a8f
QY
203 if [ -n "$2" ]; then
204 inst="$1-$2"
205 else
206 inst="$1"
207 fi
208
209 if ! started "$inst" ; then
210 echo -n " ($inst)"
211 return 0
212 else
213 PIDFILE=`pidfile $inst`
214 PID=`cat $PIDFILE 2>/dev/null`
215 kill -2 $PID 2>/dev/null
216 #
217 # Now we have to wait until $DAEMON has _really_ stopped.
218 #
219 if test -n "$PID" && kill -0 $PID 2>/dev/null; then
25e87a8f
QY
220 cnt=0
221 while kill -0 $PID 2>/dev/null; do
222 cnt=`expr $cnt + 1`
223 if [ $cnt -gt 60 ]; then
224 # Waited 120 secs now, fail.
225 echo -n "Failed.. "
226 break
227 fi
228 sleep 2
25e87a8f
QY
229 done
230 fi
25e87a8f
QY
231 rm -f `pidfile $inst`
232 rm -f `vtyfile $inst`
233
234 if [ "$1" = "zebra" ]; then
235 echo -n "Stopping staticd since zebra is running"
236 stop staticd
237 fi
7ac1de8e 238 fi
df44cf00 239}
240
d8e4c438 241# Converts values from /etc/frr/daemons to all-numeric values.
651415bd 242convert_daemon_prios()
df44cf00 243{
25e87a8f
QY
244 for name in $DAEMONS zebra vtysh_enable watchfrr_enable; do
245 # First, assign the value set by the user to $value
246 eval value=\${${name}:0:3}
651415bd 247
25e87a8f
QY
248 # Daemon not activated or entry missing?
249 if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
651415bd 250
25e87a8f
QY
251 # These strings parsed for backwards compatibility.
252 if [ "$value" = "yes" -o "$value" = "true" ]; then
253 value=1;
254 fi
651415bd 255
25e87a8f
QY
256 # Zebra is threatened special. It must be between 0=off and the first
257 # user assigned value "1" so we increase all other enabled daemons' values.
258 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value=`expr "$value" + 1`; fi
651415bd 259
25e87a8f
QY
260 # If e.g. name is zebra then we set "zebra=yes".
261 eval $name=$value
262 done
df44cf00 263}
264
9473e340
DS
265# Starts watchfrr for all wanted daemons.
266start_watchfrr()
df44cf00 267{
25e87a8f
QY
268 local daemon_name
269 local daemon_prio
270 local found_one
271 local daemon_inst
272
273 # Start the monitor daemon only if desired.
274 if [ 0 -eq "$watchfrr_enable" ]; then
275 return
276 fi
277
278 # Check variable type
10ea85ee
DL
279 if declare -p watchfrr_options | grep -q '^declare \-a'; then
280 # old array support
281 watchfrr_options="${watchfrr_options[@]}"
25e87a8f
QY
282 fi
283
284 # Which daemons have been started?
285 found_one=0
286 for daemon_name in $DAEMONS; do
287 eval daemon_prio=\$$daemon_name
288 if [ "$daemon_prio" -gt 0 ]; then
289 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
290 if [ -n "$daemon_inst" ]; then
291 for inst in ${daemon_inst}; do
292 eval "inst_disable=\${${daemon_name}_${inst}}"
293 if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then
294 if check_daemon $daemon_name $inst; then
10ea85ee 295 watchfrr_options="$watchfrr_options ${daemon_name}-${inst}"
25e87a8f
QY
296 fi
297 fi
298 done
299 else
300 if check_daemon $daemon_name; then
10ea85ee 301 watchfrr_options="$watchfrr_options $daemon_name"
25e87a8f
QY
302 fi
303 fi
304 found_one=1
305 fi
306 done
307
308 # Start if at least one daemon is activated.
309 if [ $found_one -eq 1 ]; then
25e87a8f
QY
310 start watchfrr
311 echo "."
312 fi
df44cf00 313}
314
9473e340
DS
315# Stopps watchfrr.
316stop_watchfrr()
df44cf00 317{
25e87a8f
QY
318 echo -n "Stopping Frr monitor daemon:"
319 stop watchfrr
320 echo "."
651415bd
DS
321}
322
323# Stops all daemons that have a lower level of priority than the given.
324# (technically if daemon_prio >= wanted_prio)
325stop_prio()
326{
25e87a8f
QY
327 local wanted_prio
328 local daemon_prio
329 local daemon_list
330 local daemon_inst
331 local inst
332
333 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
334 daemon=${BASH_REMATCH[1]}
335 inst=${BASH_REMATCH[2]}
336 else
337 daemon="$2"
338 fi
339
340 wanted_prio=$1
341 daemon_list=${daemon:-$DAEMONS}
342
343 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
344
345 for prio_i in `seq 10 -1 $wanted_prio`; do
346 for daemon_name in $daemon_list; do
347 eval daemon_prio=\${${daemon_name}:0:3}
348 daemon_inst=""
349 if [ $daemon_prio -eq $prio_i ]; then
350 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
351 if [ -n "$daemon_inst" ]; then
352 for i in ${daemon_inst}; do
353 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
354 stop "$daemon_name" "$inst"
355 elif [ x"$inst" == x ]; then
356 stop "$daemon_name" "$i"
357 fi
358 done
359 else
360 stop "$daemon_name"
361 fi
362 fi
363 done
364 done
365
366 echo "."
367 if [ -z "$inst" ]; then
368 # Now stop other daemons that're prowling, coz the daemons file changed
369 echo -n "Stopping other frr daemons"
370 if [ -n "$daemon" ]; then
371 eval "file_list_suffix="$V_PATH"/"$daemon*""
372 else
373 eval "file_list_suffix="$V_PATH/*""
374 fi
375 for pidfile in $file_list_suffix.pid; do
376 PID=`cat $pidfile 2>/dev/null`
377 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
378 echo -n "."
379 rm -rf "$pidfile"
380 done
381 echo "."
382
383 echo -n "Removing remaining .vty files"
384 for vtyfile in $file_list_suffix.vty; do
385 rm -rf "$vtyfile"
386 done
387 echo "."
388 fi
651415bd
DS
389}
390
391# Starts all daemons that have a higher level of priority than the given.
392# (technically if daemon_prio <= wanted_prio)
393start_prio()
394{
25e87a8f
QY
395 local wanted_prio
396 local daemon_prio
397 local daemon_list
398 local daemon_name
399 local daemon_inst
400 local inst
401
402 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
403 daemon=${BASH_REMATCH[1]}
404 inst=${BASH_REMATCH[2]}
405 else
406 daemon="$2"
407 fi
408
409 wanted_prio=$1
410 daemon_list=${daemon:-$DAEMONS}
411
25e87a8f
QY
412 for prio_i in `seq 1 $wanted_prio`; do
413 for daemon_name in $daemon_list; do
414 eval daemon_prio=\$${daemon_name}
415 daemon_inst=""
416 if [ $daemon_prio -eq $prio_i ]; then
417 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
418 if [ -n "$daemon_inst" ]; then
419 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
420 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
421 exit 1
422 fi
423 # Check if we're starting again by switching from single instance
424 # to MI version
425 if started "$daemon_name"; then
426 PIDFILE=`pidfile $daemon_name`
427 ${SSD} \
428 --stop --quiet --oknodo \
429 --pidfile "$PIDFILE" \
430 --exec "$D_PATH/$daemon_name"
431
432 rm -f `pidfile $1`
433 rm -f `vtyfile $1`
434 fi
435
436 for i in ${daemon_inst}; do
437 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
438 start "$daemon_name" "$inst"
439 elif [ x"$inst" == x ]; then
440 start "$daemon_name" "$i"
441 fi
442 done
443 else
444 # Check if we're starting again by switching from
445 # single instance to MI version
446 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
447 for pidfile in $file_list_suffix.pid; do
448 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
25e87a8f
QY
449 rm -rf "$pidfile"
450 done
451 for vtyfile in $file_list_suffix.vty; do
452 rm -rf "$vtyfile"
453 done
454
455 start "$daemon_name"
456 fi
457 fi
458 done
459 done
df44cf00 460}
461
651415bd 462check_status()
df44cf00 463{
25e87a8f
QY
464 local daemon_name
465 local daemon_prio
466 local daemon_inst
467 local failed_status=0
468
469 if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
470 daemon=${BASH_REMATCH[1]}
471 inst=${BASH_REMATCH[2]}
472 else
473 daemon="$1"
474 fi
475
476 daemon_list=${daemon:-$DAEMONS}
477
478 # Which daemons have been started?
479 for daemon_name in $daemon_list; do
480 eval daemon_prio=\$$daemon_name
481 if [ "$daemon_prio" -gt 0 ]; then
482 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
483 if [ -n "$daemon_inst" ]; then
484 for i in ${daemon_inst}; do
485 if [ -n "$inst" -a "$inst" = "$i" ]; then
486 started "$1" "log" || failed_status=$?
487 elif [ -z "$inst" ]; then
488 started "$daemon_name-$i" "log" || failed_status=$?
489 fi
490 done
491 else
492 started "$daemon_name" "log" || failed_status=$?
493 fi
494 fi
495 done
496
497 # All daemons that need to have been started are up and running
498 return $failed_status
df44cf00 499}
500
651415bd
DS
501#########################################################
502# Main program #
503#########################################################
504
505# Config broken but script must exit silently.
506[ ! -r "$C_PATH/daemons" ] && exit 0
507
508# Load configuration
509. "$C_PATH/daemons"
a55578f6
CF
510if [ -e "$C_PATH/daemons.conf" ]; then
511 . "$C_PATH/daemons.conf"
512fi
651415bd
DS
513
514# Read configuration variable file if it is present
d8e4c438 515[ -r /etc/default/frr ] && . /etc/default/frr
651415bd 516
68495906
DL
517if test -z "$frr_profile"; then
518 # try to autodetect config profile
519 if test -d /etc/cumulus; then
520 frr_profile=datacenter
521 # elif test ...; then
522 # -- add your distro/system here
523 elif test -n "$FRR_DEFAULT_PROFILE"; then
524 frr_profile="$FRR_DEFAULT_PROFILE"
525 fi
526fi
527test -n "$frr_profile" && frr_global_options="$frr_global_options -F $frr_profile"
528
651415bd
DS
529MAX_INSTANCES=${MAX_INSTANCES:=5}
530
531# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
532convert_daemon_prios
533
534if [ ! -d $V_PATH ]; then
25e87a8f
QY
535 echo "Creating $V_PATH"
536 mkdir -p $V_PATH
537 chownfrr $V_PATH
538 chmod 755 /$V_PATH
651415bd
DS
539fi
540
541if [ -n "$3" ] && [ "$3" != "all" ]; then
25e87a8f 542 dmn="$2"-"$3"
651415bd 543elif [ -n "$2" ] && [ "$2" != "all" ]; then
25e87a8f 544 dmn="$2"
651415bd
DS
545fi
546
df44cf00 547case "$1" in
25e87a8f
QY
548 start)
549 # Try to load this necessary (at least for 2.6) module.
550 if [ -d /lib/modules/`uname -r` ] ; then
551 echo "Loading capability module if not yet done."
552 set +e; LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"; set -e
553 fi
554
555 # Start all daemons
556 cd $C_PATH/
557 if [ "$2" != "watchfrr" ]; then
558 start_prio 10 $dmn
559 fi
560 start_watchfrr
561 vtysh_b
562 ;;
563
564 1|2|3|4|5|6|7|8|9|10)
565 # Stop/start daemons for the appropriate priority level
566 stop_prio $1
567 start_prio $1
568 vtysh_b
569 ;;
570
571 stop|0)
572 # Stop all daemons at level '0' or 'stop'
573 stop_watchfrr
574 if [ "$dmn" != "watchfrr" ]; then
575 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
576 stop_prio 0 $dmn
577 fi
578
db6e0503 579 if [ -n "$dmn" -a "$dmn" != "zebra" ]; then
25e87a8f
QY
580 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
581 start_watchfrr
582 fi
583 ;;
584
585 reload)
586 # Just apply the commands that have changed, no restart necessary
587 if [ ! -x "$RELOAD_SCRIPT" ]; then
588 echo "Please install frr-pythontools package. Required for reload"
589 exit 0
590 fi
591
592 NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}"
593 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
594 echo "Applying only incremental changes to running configuration from frr.conf"
595 "$RELOAD_SCRIPT" --reload $C_PATH/frr.conf
596 exit $?
597 ;;
598
599 status)
600 check_status $dmn
601 exit $?
602 ;;
603
604 restart|force-reload)
605 $0 stop $dmn
606 sleep 1
607 $0 start $dmn
608 ;;
609
610 *)
611 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
612 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
613 echo " reload applies only modifications from the running config to all daemons."
614 echo " reload neither restarts starts any daemon nor starts any new ones."
615 echo " Read /usr/share/doc/frr/README.Debian for details."
616 exit 1
617 ;;
df44cf00 618esac
619
651415bd 620echo "Exiting from the script"
df44cf00 621exit 0