]> git.proxmox.com Git - mirror_frr.git/blame - tools/frr
Merge branch 'master' into EIGRP
[mirror_frr.git] / tools / frr
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
d8e4c438
DS
17D_PATH=/usr/lib/frr
18C_PATH=/etc/frr
19V_PATH=/var/run/frr
651415bd 20
d8e4c438
DS
21# Local Daemon selection may be done by using /etc/frr/daemons.
22# See /usr/share/doc/frr/README.Debian.gz for further information.
9473e340 23# Keep zebra first and do not list watchfrr!
e6ddb8e2 24DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd"
651415bd 25MAX_INSTANCES=5
d8e4c438 26RELOAD_SCRIPT=/usr/lib/frr/frr-reload.py
651415bd
DS
27
28. /lib/lsb/init-functions
29
d8e4c438
DS
30if [ -f /usr/lib/frr/ssd ]; then
31 SSD=/usr/lib/frr/ssd
d84fd25b
DS
32else
33 SSD=`which start-stop-daemon`
34fi
35
651415bd
DS
36# Print the name of the pidfile.
37pidfile()
38{
39 echo "$V_PATH/$1.pid"
40}
41
42# Print the name of the vtysh.
43vtyfile()
44{
45 echo "$V_PATH/$1.vty"
46}
47
48# Check if daemon is started by using the pidfile.
49started()
50{
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 $?
54 else
55 kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1
56 return 0
57 fi
58}
59
60# Loads the config via vtysh -b if configured to do so.
61vtysh_b ()
62{
63 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
e20dc2ba 64 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf ]; then
651415bd
DS
65 /usr/bin/vtysh -b -n
66 fi
67}
68
69# Check if the daemon is activated and if its executable and config files
70# are in place.
71# params: daemon name
72# returns: 0=ok, 1=error
73check_daemon()
74{
75 # If the integrated config file is used the others are not checked.
e20dc2ba 76 if [ -r "$C_PATH/frr.conf" ]; then
651415bd
DS
77 return 0
78 fi
79
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)
9473e340 82 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
651415bd
DS
83 # check for daemon binary
84 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
85
86 # check for config file
87 if [ -n "$2" ]; then
88 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
89 touch "$C_PATH/$1-$2.conf"
d8e4c438 90 chown frr:frr "$C_PATH/$1-$2.conf"
651415bd
DS
91 fi
92 elif [ ! -r "$C_PATH/$1.conf" ]; then
93 touch "$C_PATH/$1.conf"
d8e4c438 94 chown frr:frr "$C_PATH/$1.conf"
651415bd
DS
95 fi
96 fi
97 return 0
98}
99
100# Starts the server if it's not alrady running according to the pid file.
d8e4c438 101# The Frr daemons creates the pidfile when starting.
651415bd 102start()
df44cf00 103{
651415bd 104 ulimit -n $MAX_FDS
9473e340 105 if [ "$1" = "watchfrr" ]; then
df44cf00 106
9473e340 107 # We may need to restart watchfrr if new daemons are added and/or
651415bd
DS
108 # removed
109 if started "$1" ; then
9473e340 110 stop watchfrr
651415bd 111 else
9473e340 112 # Echo only once. watchfrr is printed in the stop above
651415bd
DS
113 echo -n " $1"
114 fi
df44cf00 115
d8e4c438
DS
116 if [ -e /var/run/frr/watchfrr.started ] ; then
117 rm /var/run/frr/watchfrr.started
207e0d7a 118 fi
d84fd25b 119 ${SSD} \
651415bd
DS
120 --start \
121 --pidfile=`pidfile $1` \
122 --exec "$D_PATH/$1" \
123 -- \
9473e340 124 "${watchfrr_options[@]}"
207e0d7a
DS
125 for i in `seq 1 10`;
126 do
d8e4c438 127 if [ -e /var/run/frr/watchfrr.started ] ; then
207e0d7a
DS
128 break
129 else
130 sleep 1
131 fi
132 done
651415bd
DS
133 elif [ -n "$2" ]; then
134 echo -n " $1-$2"
135 if ! check_daemon $1 $2 ; then
136 echo -n " (binary does not exist)"
137 return;
138 fi
139
d84fd25b 140 ${SSD} \
651415bd
DS
141 --start \
142 --pidfile=`pidfile $1-$2` \
143 --exec "$D_PATH/$1" \
144 -- \
145 `eval echo "$""$1""_options"` -n "$2"
146 else
147 echo -n " $1"
148 if ! check_daemon $1; then
149 echo -n " (binary does not exist)"
150 return;
151 fi
152
d84fd25b 153 ${SSD} \
651415bd
DS
154 --start \
155 --pidfile=`pidfile $1` \
156 --exec "$D_PATH/$1" \
157 -- \
158 `eval echo "$""$1""_options"`
159 fi
160}
161
162# Stop the daemon given in the parameter, printing its name to the terminal.
163stop()
164{
165 local inst
166
167 if [ -n "$2" ]; then
168 inst="$1-$2"
169 else
170 inst="$1"
df44cf00 171 fi
172
651415bd
DS
173 if ! started "$inst" ; then
174 echo -n " ($inst)"
175 return 0
176 else
177 PIDFILE=`pidfile $inst`
178 PID=`cat $PIDFILE 2>/dev/null`
d84fd25b 179 ${SSD} --stop --quiet --retry=TERM/30/KILL/5 --oknodo --pidfile "$PIDFILE" --exec "$D_PATH/$1"
651415bd
DS
180 #
181 # Now we have to wait until $DAEMON has _really_ stopped.
182 #
183 if test -n "$PID" && kill -0 $PID 2>/dev/null; then
184 echo -n " (waiting) ."
185 cnt=0
186 while kill -0 $PID 2>/dev/null; do
187 cnt=`expr $cnt + 1`
188 if [ $cnt -gt 60 ]; then
189 # Waited 120 secs now, fail.
190 echo -n "Failed.. "
191 break
192 fi
193 sleep 2
194 echo -n "."
195 done
196 fi
197 echo -n " $inst"
198 rm -f `pidfile $inst`
199 rm -f `vtyfile $inst`
df44cf00 200 fi
201}
202
d8e4c438 203# Converts values from /etc/frr/daemons to all-numeric values.
651415bd 204convert_daemon_prios()
df44cf00 205{
9473e340 206 for name in $DAEMONS zebra vtysh_enable watchfrr_enable; do
651415bd
DS
207 # First, assign the value set by the user to $value
208 eval value=\${${name}:0:3}
209
210 # Daemon not activated or entry missing?
211 if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
212
213 # These strings parsed for backwards compatibility.
214 if [ "$value" = "yes" -o "$value" = "true" ]; then
215 value=1;
216 fi
217
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
221
222 # If e.g. name is zebra then we set "zebra=yes".
223 eval $name=$value
224 done
df44cf00 225}
226
9473e340
DS
227# Starts watchfrr for all wanted daemons.
228start_watchfrr()
df44cf00 229{
651415bd
DS
230 local daemon_name
231 local daemon_prio
232 local found_one
233 local daemon_inst
234
235 # Start the monitor daemon only if desired.
9473e340 236 if [ 0 -eq "$watchfrr_enable" ]; then
651415bd
DS
237 return
238 fi
239
240 # Check variable type
9473e340 241 if ! declare -p watchfrr_options | grep -q '^declare \-a'; then
651415bd 242 echo
d8e4c438 243 echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!"
651415bd
DS
244 echo "ERROR: Please convert config file and restart!"
245 exit 1
246 fi
247
248 # Which daemons have been started?
249 found_one=0
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
9473e340 259 watchfrr_options+=("${daemon_name}-${inst}")
651415bd
DS
260 fi
261 fi
262 done
263 else
264 if check_daemon $daemon_name; then
9473e340 265 watchfrr_options+=($daemon_name)
651415bd
DS
266 fi
267 fi
268 found_one=1
269 fi
270 done
271
272 # Start if at least one daemon is activated.
273 if [ $found_one -eq 1 ]; then
d8e4c438 274 echo -n "Starting Frr monitor daemon:"
9473e340 275 start watchfrr
651415bd
DS
276 echo "."
277 fi
df44cf00 278}
279
9473e340
DS
280# Stopps watchfrr.
281stop_watchfrr()
df44cf00 282{
d8e4c438 283 echo -n "Stopping Frr monitor daemon:"
9473e340 284 stop watchfrr
651415bd
DS
285 echo "."
286}
287
288# Stops all daemons that have a lower level of priority than the given.
289# (technically if daemon_prio >= wanted_prio)
290stop_prio()
291{
292 local wanted_prio
293 local daemon_prio
294 local daemon_list
295 local daemon_inst
296 local inst
297
298 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
299 daemon=${BASH_REMATCH[1]}
300 inst=${BASH_REMATCH[2]}
301 else
302 daemon="$2"
303 fi
304
305 wanted_prio=$1
306 daemon_list=${daemon:-$DAEMONS}
307
d8e4c438 308 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
651415bd
DS
309
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}
313 daemon_inst=""
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"
322 fi
323 done
324 else
325 stop "$daemon_name"
326 fi
327 fi
328 done
329 done
330
331 echo "."
332 if [ -z "$inst" ]; then
333 # Now stop other daemons that're prowling, coz the daemons file changed
d8e4c438 334 echo -n "Stopping other frr daemons"
651415bd
DS
335 if [ -n "$daemon" ]; then
336 eval "file_list_suffix="$V_PATH"/"$daemon*""
337 else
338 eval "file_list_suffix="$V_PATH/*""
339 fi
340 for pidfile in $file_list_suffix.pid; do
341 PID=`cat $pidfile 2>/dev/null`
d84fd25b 342 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
651415bd
DS
343 echo -n "."
344 rm -rf "$pidfile"
345 done
346 echo "."
347
348 echo -n "Removing remaining .vty files"
349 for vtyfile in $file_list_suffix.vty; do
350 rm -rf "$vtyfile"
351 done
352 echo "."
353 fi
354}
355
356# Starts all daemons that have a higher level of priority than the given.
357# (technically if daemon_prio <= wanted_prio)
358start_prio()
359{
360 local wanted_prio
361 local daemon_prio
362 local daemon_list
363 local daemon_name
364 local daemon_inst
365 local inst
366
367 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
368 daemon=${BASH_REMATCH[1]}
369 inst=${BASH_REMATCH[2]}
370 else
371 daemon="$2"
372 fi
373
374 wanted_prio=$1
375 daemon_list=${daemon:-$DAEMONS}
376
d8e4c438 377 echo -n "Starting Frr daemons (prio:$wanted_prio):"
651415bd
DS
378
379 for prio_i in `seq 1 $wanted_prio`; do
380 for daemon_name in $daemon_list; do
381 eval daemon_prio=\$${daemon_name}
382 daemon_inst=""
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"
388 exit 1
389 fi
390 # Check if we're starting again by switching from single instance
391 # to MI version
392 if started "$daemon_name"; then
393 PIDFILE=`pidfile $daemon_name`
d84fd25b 394 ${SSD} \
651415bd
DS
395 --stop --quiet --oknodo \
396 --pidfile "$PIDFILE" \
397 --exec "$D_PATH/$daemon_name"
398
399 rm -f `pidfile $1`
400 rm -f `vtyfile $1`
401 fi
402
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"
408 fi
409 done
410 else
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
d84fd25b 415 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
651415bd
DS
416 echo -n "."
417 rm -rf "$pidfile"
418 done
419 for vtyfile in $file_list_suffix.vty; do
420 rm -rf "$vtyfile"
421 done
422
423 start "$daemon_name"
424 fi
425 fi
426 done
427 done
428 echo "."
df44cf00 429}
430
651415bd 431check_status()
df44cf00 432{
651415bd
DS
433 local daemon_name
434 local daemon_prio
435 local daemon_inst
436 local failed_status=0
437
438 if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
439 daemon=${BASH_REMATCH[1]}
440 inst=${BASH_REMATCH[2]}
441 else
442 daemon="$1"
443 fi
444
445 daemon_list=${daemon:-$DAEMONS}
446
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=$?
458 fi
459 done
460 else
461 started "$daemon_name" "log" || failed_status=$?
462 fi
463 fi
464 done
465
466 # All daemons that need to have been started are up and running
467 return $failed_status
df44cf00 468}
469
651415bd
DS
470#########################################################
471# Main program #
472#########################################################
473
474# Config broken but script must exit silently.
475[ ! -r "$C_PATH/daemons" ] && exit 0
476
477# Load configuration
478. "$C_PATH/daemons"
479. "$C_PATH/debian.conf"
480
481# Read configuration variable file if it is present
d8e4c438 482[ -r /etc/default/frr ] && . /etc/default/frr
651415bd
DS
483
484MAX_INSTANCES=${MAX_INSTANCES:=5}
485
486# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
487convert_daemon_prios
488
489if [ ! -d $V_PATH ]; then
490 echo "Creating $V_PATH"
491 mkdir -p $V_PATH
d8e4c438 492 chown frr:frr $V_PATH
651415bd
DS
493 chmod 755 /$V_PATH
494fi
495
496if [ -n "$3" ] && [ "$3" != "all" ]; then
497 dmn="$2"-"$3"
498elif [ -n "$2" ] && [ "$2" != "all" ]; then
499 dmn="$2"
500fi
501
df44cf00 502case "$1" in
651415bd
DS
503 start)
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
508 fi
509
510 # Start all daemons
511 cd $C_PATH/
9473e340 512 if [ "$2" != "watchfrr" ]; then
651415bd
DS
513 start_prio 10 $dmn
514 fi
9473e340 515 start_watchfrr
207e0d7a 516 vtysh_b
651415bd
DS
517 ;;
518
519 1|2|3|4|5|6|7|8|9|10)
520 # Stop/start daemons for the appropriate priority level
521 stop_prio $1
522 start_prio $1
523 vtysh_b
524 ;;
525
526 stop|0)
527 # Stop all daemons at level '0' or 'stop'
9473e340
DS
528 stop_watchfrr
529 if [ "$dmn" != "watchfrr" ]; then
651415bd
DS
530 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
531 stop_prio 0 $dmn
532 fi
533
534 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
23b1f334
DD
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
651415bd 541 ip route flush proto zebra
23b1f334
DD
542 ip route flush proto isis
543
651415bd
DS
544 else
545 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
9473e340 546 start_watchfrr
651415bd
DS
547 fi
548 ;;
549
550 reload)
551 # Just apply the commands that have changed, no restart necessary
d8e4c438 552 [ ! -x "$RELOAD_SCRIPT" ] && echo "frr-reload script not available" && exit 0
e20dc2ba 553 NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}"
651415bd 554 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
e20dc2ba
MB
555 echo "Applying only incremental changes to running configuration from frr.conf"
556 "$RELOAD_SCRIPT" --reload /etc/frr/frr.conf
651415bd
DS
557 exit $?
558 ;;
559
560 status)
561 check_status $dmn
562 exit $?
563 ;;
564
565 restart|force-reload)
566 $0 stop $dmn
567 sleep 1
568 $0 start $dmn
569 ;;
570
571 *)
d8e4c438
DS
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."
651415bd
DS
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."
d8e4c438 576 echo " Read /usr/share/doc/frr/README.Debian for details."
651415bd
DS
577 exit 1
578 ;;
df44cf00 579esac
580
651415bd 581echo "Exiting from the script"
df44cf00 582exit 0