]> git.proxmox.com Git - mirror_frr.git/blame - tools/frr.in
eigrpd: eigrp usage of uint32_t to struct in_addr for router_id data
[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{
10ea85ee
DL
118 local dmn inst
119 dmn="$1"
120 inst="$2"
121
122 ulimit -n $MAX_FDS > /dev/null 2> /dev/null
123 if [ "$dmn" = "watchfrr" ]; then
25e87a8f
QY
124
125 # We may need to restart watchfrr if new daemons are added and/or
126 # removed
10ea85ee 127 if started "$dmn" ; then
25e87a8f
QY
128 stop watchfrr
129 else
130 # Echo only once. watchfrr is printed in the stop above
10ea85ee 131 echo -n " $dmn"
25e87a8f
QY
132 fi
133
10ea85ee 134 eval "set - $watchfrr_options"
25e87a8f
QY
135 ${SSD} \
136 --start \
10ea85ee
DL
137 --pidfile=`pidfile $dmn` \
138 --exec "$D_PATH/$dmn" \
25e87a8f 139 -- \
10ea85ee 140 "$@"
25e87a8f 141
10ea85ee
DL
142 elif [ -n "$inst" ]; then
143 echo -n " $dmn-$inst"
144 if ! check_daemon $dmn $inst ; then
25e87a8f
QY
145 echo -n " (binary does not exist)"
146 return;
147 fi
148
149 ${SSD} \
150 --start \
10ea85ee
DL
151 --pidfile=`pidfile $dmn-$inst` \
152 --exec "$D_PATH/$dmn" \
25e87a8f 153 -- \
10ea85ee 154 `eval echo "$""$dmn""_options"` -n "$inst"
25e87a8f 155 else
10ea85ee 156 if ! check_daemon $dmn; then
25e87a8f
QY
157 echo -n " (binary does not exist)"
158 return;
159 fi
160
161 if [ "$valgrind_enable" = "yes" ]; then
162 ${SSD} \
163 --start \
10ea85ee 164 --pidfile=`pidfile $dmn` \
25e87a8f 165 --exec "$valgrind" \
10ea85ee
DL
166 -- --trace-children=no --leak-check=full --log-file=/var/log/frr/$dmn-valgrind.log $D_PATH/$dmn \
167 `eval echo "$""$dmn""_options"`
25e87a8f
QY
168 else
169 ${SSD} \
170 --start \
10ea85ee
DL
171 --pidfile=`pidfile $dmn` \
172 --exec "$D_PATH/$dmn" \
25e87a8f 173 -- \
10ea85ee 174 `eval echo "$""$dmn""_options"`
25e87a8f
QY
175 fi
176 fi
7ac1de8e
DS
177
178 # Start the staticd automatically
10ea85ee 179 if [ "$dmn" = "zebra" ]; then
25e87a8f
QY
180 echo -n "starting staticd since zebra is running"
181 if ! check_daemon staticd ; then
182 echo -n " (binary does not exist)"
183 return;
184 fi
185
186 ${SSD} \
187 --start \
188 --pidfile=`pidfile staticd` \
189 --exec "$D_PATH/staticd" \
190 -- \
191 `eval echo "$"staticd"_options"`
7ac1de8e 192 fi
651415bd
DS
193}
194
195# Stop the daemon given in the parameter, printing its name to the terminal.
196stop()
197{
25e87a8f 198 local inst
7ac1de8e 199
25e87a8f
QY
200 if [ -n "$2" ]; then
201 inst="$1-$2"
202 else
203 inst="$1"
204 fi
205
206 if ! started "$inst" ; then
207 echo -n " ($inst)"
208 return 0
209 else
210 PIDFILE=`pidfile $inst`
211 PID=`cat $PIDFILE 2>/dev/null`
212 kill -2 $PID 2>/dev/null
213 #
214 # Now we have to wait until $DAEMON has _really_ stopped.
215 #
216 if test -n "$PID" && kill -0 $PID 2>/dev/null; then
25e87a8f
QY
217 cnt=0
218 while kill -0 $PID 2>/dev/null; do
219 cnt=`expr $cnt + 1`
220 if [ $cnt -gt 60 ]; then
221 # Waited 120 secs now, fail.
222 echo -n "Failed.. "
223 break
224 fi
225 sleep 2
25e87a8f
QY
226 done
227 fi
25e87a8f
QY
228 rm -f `pidfile $inst`
229 rm -f `vtyfile $inst`
230
231 if [ "$1" = "zebra" ]; then
232 echo -n "Stopping staticd since zebra is running"
233 stop staticd
234 fi
7ac1de8e 235 fi
df44cf00 236}
237
d8e4c438 238# Converts values from /etc/frr/daemons to all-numeric values.
651415bd 239convert_daemon_prios()
df44cf00 240{
25e87a8f
QY
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}
651415bd 244
25e87a8f
QY
245 # Daemon not activated or entry missing?
246 if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
651415bd 247
25e87a8f
QY
248 # These strings parsed for backwards compatibility.
249 if [ "$value" = "yes" -o "$value" = "true" ]; then
250 value=1;
251 fi
651415bd 252
25e87a8f
QY
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
651415bd 256
25e87a8f
QY
257 # If e.g. name is zebra then we set "zebra=yes".
258 eval $name=$value
259 done
df44cf00 260}
261
9473e340
DS
262# Starts watchfrr for all wanted daemons.
263start_watchfrr()
df44cf00 264{
25e87a8f
QY
265 local daemon_name
266 local daemon_prio
267 local found_one
268 local daemon_inst
269
270 # Start the monitor daemon only if desired.
271 if [ 0 -eq "$watchfrr_enable" ]; then
272 return
273 fi
274
275 # Check variable type
10ea85ee
DL
276 if declare -p watchfrr_options | grep -q '^declare \-a'; then
277 # old array support
278 watchfrr_options="${watchfrr_options[@]}"
25e87a8f
QY
279 fi
280
281 # Which daemons have been started?
282 found_one=0
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
10ea85ee 292 watchfrr_options="$watchfrr_options ${daemon_name}-${inst}"
25e87a8f
QY
293 fi
294 fi
295 done
296 else
297 if check_daemon $daemon_name; then
10ea85ee 298 watchfrr_options="$watchfrr_options $daemon_name"
25e87a8f
QY
299 fi
300 fi
301 found_one=1
302 fi
303 done
304
305 # Start if at least one daemon is activated.
306 if [ $found_one -eq 1 ]; then
25e87a8f
QY
307 start watchfrr
308 echo "."
309 fi
df44cf00 310}
311
9473e340
DS
312# Stopps watchfrr.
313stop_watchfrr()
df44cf00 314{
25e87a8f
QY
315 echo -n "Stopping Frr monitor daemon:"
316 stop watchfrr
317 echo "."
651415bd
DS
318}
319
320# Stops all daemons that have a lower level of priority than the given.
321# (technically if daemon_prio >= wanted_prio)
322stop_prio()
323{
25e87a8f
QY
324 local wanted_prio
325 local daemon_prio
326 local daemon_list
327 local daemon_inst
328 local inst
329
330 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
331 daemon=${BASH_REMATCH[1]}
332 inst=${BASH_REMATCH[2]}
333 else
334 daemon="$2"
335 fi
336
337 wanted_prio=$1
338 daemon_list=${daemon:-$DAEMONS}
339
340 echo -n "Stopping Frr daemons (prio:$wanted_prio):"
341
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}
345 daemon_inst=""
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"
354 fi
355 done
356 else
357 stop "$daemon_name"
358 fi
359 fi
360 done
361 done
362
363 echo "."
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*""
369 else
370 eval "file_list_suffix="$V_PATH/*""
371 fi
372 for pidfile in $file_list_suffix.pid; do
373 PID=`cat $pidfile 2>/dev/null`
374 ${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
375 echo -n "."
376 rm -rf "$pidfile"
377 done
378 echo "."
379
380 echo -n "Removing remaining .vty files"
381 for vtyfile in $file_list_suffix.vty; do
382 rm -rf "$vtyfile"
383 done
384 echo "."
385 fi
651415bd
DS
386}
387
388# Starts all daemons that have a higher level of priority than the given.
389# (technically if daemon_prio <= wanted_prio)
390start_prio()
391{
25e87a8f
QY
392 local wanted_prio
393 local daemon_prio
394 local daemon_list
395 local daemon_name
396 local daemon_inst
397 local inst
398
399 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
400 daemon=${BASH_REMATCH[1]}
401 inst=${BASH_REMATCH[2]}
402 else
403 daemon="$2"
404 fi
405
406 wanted_prio=$1
407 daemon_list=${daemon:-$DAEMONS}
408
25e87a8f
QY
409 for prio_i in `seq 1 $wanted_prio`; do
410 for daemon_name in $daemon_list; do
411 eval daemon_prio=\$${daemon_name}
412 daemon_inst=""
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"
418 exit 1
419 fi
420 # Check if we're starting again by switching from single instance
421 # to MI version
422 if started "$daemon_name"; then
423 PIDFILE=`pidfile $daemon_name`
424 ${SSD} \
425 --stop --quiet --oknodo \
426 --pidfile "$PIDFILE" \
427 --exec "$D_PATH/$daemon_name"
428
429 rm -f `pidfile $1`
430 rm -f `vtyfile $1`
431 fi
432
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"
438 fi
439 done
440 else
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"
25e87a8f
QY
446 rm -rf "$pidfile"
447 done
448 for vtyfile in $file_list_suffix.vty; do
449 rm -rf "$vtyfile"
450 done
451
452 start "$daemon_name"
453 fi
454 fi
455 done
456 done
df44cf00 457}
458
651415bd 459check_status()
df44cf00 460{
25e87a8f
QY
461 local daemon_name
462 local daemon_prio
463 local daemon_inst
464 local failed_status=0
465
466 if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
467 daemon=${BASH_REMATCH[1]}
468 inst=${BASH_REMATCH[2]}
469 else
470 daemon="$1"
471 fi
472
473 daemon_list=${daemon:-$DAEMONS}
474
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=$?
486 fi
487 done
488 else
489 started "$daemon_name" "log" || failed_status=$?
490 fi
491 fi
492 done
493
494 # All daemons that need to have been started are up and running
495 return $failed_status
df44cf00 496}
497
651415bd
DS
498#########################################################
499# Main program #
500#########################################################
501
502# Config broken but script must exit silently.
503[ ! -r "$C_PATH/daemons" ] && exit 0
504
505# Load configuration
506. "$C_PATH/daemons"
82e6e358 507. "$C_PATH/daemons.conf"
651415bd
DS
508
509# Read configuration variable file if it is present
d8e4c438 510[ -r /etc/default/frr ] && . /etc/default/frr
651415bd
DS
511
512MAX_INSTANCES=${MAX_INSTANCES:=5}
513
514# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
515convert_daemon_prios
516
517if [ ! -d $V_PATH ]; then
25e87a8f
QY
518 echo "Creating $V_PATH"
519 mkdir -p $V_PATH
520 chownfrr $V_PATH
521 chmod 755 /$V_PATH
651415bd
DS
522fi
523
524if [ -n "$3" ] && [ "$3" != "all" ]; then
25e87a8f 525 dmn="$2"-"$3"
651415bd 526elif [ -n "$2" ] && [ "$2" != "all" ]; then
25e87a8f 527 dmn="$2"
651415bd
DS
528fi
529
df44cf00 530case "$1" in
25e87a8f
QY
531 start)
532 # Try to load this necessary (at least for 2.6) module.
533 if [ -d /lib/modules/`uname -r` ] ; then
534 echo "Loading capability module if not yet done."
535 set +e; LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"; set -e
536 fi
537
538 # Start all daemons
539 cd $C_PATH/
540 if [ "$2" != "watchfrr" ]; then
541 start_prio 10 $dmn
542 fi
543 start_watchfrr
544 vtysh_b
545 ;;
546
547 1|2|3|4|5|6|7|8|9|10)
548 # Stop/start daemons for the appropriate priority level
549 stop_prio $1
550 start_prio $1
551 vtysh_b
552 ;;
553
554 stop|0)
555 # Stop all daemons at level '0' or 'stop'
556 stop_watchfrr
557 if [ "$dmn" != "watchfrr" ]; then
558 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
559 stop_prio 0 $dmn
560 fi
561
562 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
563 echo "Removing all routes made by FRR."
564 # Specific values for each proto can be found
565 # in /etc/iproute2/rt_protos as well as FRR
566 # specific ones in /etc/iproute2/rt_protos.d
567 # Additionally if a new protocol is added
568 # we need to add it here as well as
569 # in rt_netlink.h( follow the directions! )
570 ip route flush proto 4
571 ip route flush proto 11
572 ip route flush proto 42
573 ip route flush proto 186
574 ip route flush proto 187
575 ip route flush proto 188
576 ip route flush proto 189
577 ip route flush proto 190
578 ip route flush proto 191
579 ip route flush proto 192
580 ip route flush proto 193
581 ip route flush proto 194
582 ip route flush proto 195
583 ip route flush proto 196
584 ip route flush proto 197
585 else
586 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
587 start_watchfrr
588 fi
589 ;;
590
591 reload)
592 # Just apply the commands that have changed, no restart necessary
593 if [ ! -x "$RELOAD_SCRIPT" ]; then
594 echo "Please install frr-pythontools package. Required for reload"
595 exit 0
596 fi
597
598 NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}"
599 [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1
600 echo "Applying only incremental changes to running configuration from frr.conf"
601 "$RELOAD_SCRIPT" --reload $C_PATH/frr.conf
602 exit $?
603 ;;
604
605 status)
606 check_status $dmn
607 exit $?
608 ;;
609
610 restart|force-reload)
611 $0 stop $dmn
612 sleep 1
613 $0 start $dmn
614 ;;
615
616 *)
617 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
618 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
619 echo " reload applies only modifications from the running config to all daemons."
620 echo " reload neither restarts starts any daemon nor starts any new ones."
621 echo " Read /usr/share/doc/frr/README.Debian for details."
622 exit 1
623 ;;
df44cf00 624esac
625
651415bd 626echo "Exiting from the script"
df44cf00 627exit 0