]> git.proxmox.com Git - mirror_frr.git/blame - redhat/frr.init
Merge pull request #2684 from netravnen/feature/bgpd/well-known-communities
[mirror_frr.git] / redhat / frr.init
CommitLineData
c2953ac5
MW
1#!/bin/bash
2#
3# /etc/rc.d/init.d/frr
4#
5# Start/Stop the FRR Routing daemons
6# <any general comments about this init script>
7#
8# chkconfig: 2345 15 85
9#
10# description: FRRouting (FRR) is a routing suite for IP routing protocols
11# like BGP, OSPF, RIP and others. This script contols the main
12# daemon "frr" as well as the individual protocol daemons.
13#
14### BEGIN INIT INFO
15# Provides: frr
16# Required-Start: $local_fs $network $syslog
17# Required-Stop: $local_fs $syslog
18# Should-Start: $syslog
19# Should-Stop: $network $syslog
20# Default-Start: 2 3 4 5
21# Default-Stop: 0 1 6
22# Short-Description: Start/Stop the FRR Routing daemons
23# Description: FRRouting (FRR) is a routing suite for IP routing protocols
24# like BGP, OSPF, RIP and others. This script contols the main
25# daemon "frr" as well as the individual protocol daemons.
26### END INIT INFO
27
28PATH=/bin:/usr/bin:/sbin:/usr/sbin
29D_PATH=/usr/lib/frr
30C_PATH=/etc/frr
31V_PATH=/var/run/frr
32
33# Local Daemon selection may be done by using /etc/frr/daemons.
34# See /usr/share/doc/frr/README.Debian.gz for further information.
35# Keep zebra first and do not list watchfrr!
1abe1280 36DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd pimd pbrd ldpd nhrpd eigrpd babeld"
c2953ac5
MW
37MAX_INSTANCES=5
38RELOAD_SCRIPT=/usr/lib/frr/frr-reload.py
39
40. /etc/init.d/functions
41
42# Print the name of the pidfile.
43pidfile()
44{
45 echo "$V_PATH/$1.pid"
46}
47
48# Print the name of the vtysh.
49vtyfile()
50{
51 echo "$V_PATH/$1.vty"
52}
53
54# Check if daemon is started by using the pidfile.
55started()
56{
57 [ ! -e `pidfile $1` ] && return 3
58 if [ -n "$2" ] && [ "$2" == "log" ]; then
59 status -p `pidfile $1` $1 && return 0 || return $?
60 else
61 kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1
62 return 0
63 fi
64}
65
66# Loads the config via vtysh -b if configured to do so.
67vtysh_b ()
68{
69 # Rember, that all variables have been incremented by 1 in convert_daemon_prios()
70 if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf ]; then
71 /usr/bin/vtysh -b -n
72 fi
73}
74
75# Check if the daemon is activated and if its executable and config files
76# are in place.
77# params: daemon name
78# returns: 0=ok, 1=error
79check_daemon()
80{
81 # If the integrated config file is used the others are not checked.
82 if [ -r "$C_PATH/frr.conf" ]; then
83 return 0
84 fi
85
86 # vtysh_enable has no config file nor binary so skip check.
87 # (Not sure why vtysh_enable is in this list but does not hurt)
88 if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then
89 # check for daemon binary
90 if [ ! -x "$D_PATH/$1" ]; then return 1; fi
91
92 # check for config file
93 if [ -n "$2" ]; then
94 if [ ! -r "$C_PATH/$1-$2.conf" ]; then
95 touch "$C_PATH/$1-$2.conf"
96 chown frr:frr "$C_PATH/$1-$2.conf"
97 fi
98 elif [ ! -r "$C_PATH/$1.conf" ]; then
99 touch "$C_PATH/$1.conf"
100 chown frr:frr "$C_PATH/$1.conf"
101 fi
102 fi
103 return 0
104}
105
106# Starts the server if it's not already running according to the pid file.
107# The Frr daemons creates the pidfile when starting.
108start()
109{
110 ulimit -n $MAX_FDS > /dev/null 2> /dev/null
111 if [ "$1" = "watchfrr" ]; then
112
113 # We may need to restart watchfrr if new daemons are added and/or
114 # removed
115 if started "$1" ; then
116 stop watchfrr
117 else
118 # Echo only once. watchfrr is printed in the stop above
119 echo -n " $1"
120 fi
121
122 if [ -e /var/run/frr/watchfrr.started ] ; then
123 rm /var/run/frr/watchfrr.started
124 fi
125 daemon --pidfile=`pidfile $1` "$D_PATH/$1" -d "${watchfrr_options[@]}"
126 RETVAL=$?
127 [ $RETVAL -ne 0 ] && break
128 for i in `seq 1 10`;
129 do
130 if [ -e /var/run/frr/watchfrr.started ] ; then
131 RETVAL=0
132 break
133 else
134 sleep 1
135 fi
136 done
137 RETVAL=1
138 elif [ -n "$2" ]; then
139 echo -n " $1-$2"
140 if ! check_daemon $1 $2 ; then
141 echo -n " (binary does not exist)"
142 return;
143 fi
144 daemon --pidfile=`pidfile $1-$2` "$D_PATH/$1" -d `eval echo "$""$1""_options"` -n "$2"
145 RETVAL=$?
146 else
147 echo -n " $1 "
148 if ! check_daemon $1; then
149 echo " (binary does not exist)"
150 return;
151 fi
152 daemon --pidfile=`pidfile $1` "$D_PATH/$1" -d `eval echo "$""$1""_options"`
153 RETVAL=$?
154 fi
155 echo
156 [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$1
157 return $RETVAL
158}
159
160# Stop the daemon given in the parameter, printing its name to the terminal.
161stop()
162{
163 local inst
164
165 if [ -n "$2" ]; then
166 inst="$1-$2"
167 else
168 inst="$1"
169 fi
170
171 if ! started "$inst" ; then
172 # echo -n " ($inst)"
173 return 0
174 else
175 echo -n " $inst"
176 PIDFILE=`pidfile $inst`
177 PID=`cat $PIDFILE 2>/dev/null`
178 killproc -p "$PIDFILE" "$D_PATH/$1"
179 RETVAL=$?
180 [ $RETVAL -eq 0 ] && rm -f $lockfile
181 rm -f `pidfile $inst`
182 rm -f `vtyfile $inst`
183 echo
184 return $RETVAL
185 fi
186}
187
188# Converts values from /etc/frr/daemons to all-numeric values.
189convert_daemon_prios()
190{
191 for name in $DAEMONS zebra vtysh_enable watchfrr_enable; do
192 # First, assign the value set by the user to $value
193 eval value=\${${name}:0:3}
194
195 # Daemon not activated or entry missing?
196 if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi
197
198 # These strings parsed for backwards compatibility.
199 if [ "$value" = "yes" -o "$value" = "true" ]; then
200 value=1;
201 fi
202
203 # Zebra is threatened special. It must be between 0=off and the first
204 # user assigned value "1" so we increase all other enabled daemons' values.
205 if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value=`expr "$value" + 1`; fi
206
207 # If e.g. name is zebra then we set "zebra=yes".
208 eval $name=$value
209 done
210}
211
212# Starts watchfrr for all wanted daemons.
213start_watchfrr()
214{
215 local daemon_name
216 local daemon_prio
217 local found_one
218 local daemon_inst
219
220 # Start the monitor daemon only if desired.
221 if [ 0 -eq "$watchfrr_enable" ]; then
222 return
223 fi
224
225 # Check variable type
226 if ! declare -p watchfrr_options | grep -q '^declare \-a'; then
227 echo
228 echo "ERROR: The variable watchfrr_options from /etc/frr/daemons must be a BASH array!"
229 echo "ERROR: Please convert config file and restart!"
230 exit 1
231 fi
232
233 # Which daemons have been started?
234 found_one=0
235 for daemon_name in $DAEMONS; do
236 eval daemon_prio=\$$daemon_name
237 if [ "$daemon_prio" -gt 0 ]; then
238 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
239 if [ -n "$daemon_inst" ]; then
240 for inst in ${daemon_inst}; do
241 eval "inst_disable=\${${daemon_name}_${inst}}"
242 if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then
243 if check_daemon $daemon_name $inst; then
244 watchfrr_options+=("${daemon_name}-${inst}")
245 fi
246 fi
247 done
248 else
249 if check_daemon $daemon_name; then
250 watchfrr_options+=($daemon_name)
251 fi
252 fi
253 found_one=1
254 fi
255 done
256
257 # Start if at least one daemon is activated.
258 if [ $found_one -eq 1 ]; then
259 echo "Starting FRRouting monitor daemon:"
260 start watchfrr
261 fi
262}
263
264# Stopps watchfrr.
265stop_watchfrr()
266{
267 echo "Stopping FRRouting monitor daemon:"
268 stop watchfrr
269}
270
271# Stops all daemons that have a lower level of priority than the given.
272# (technically if daemon_prio >= wanted_prio)
273stop_prio()
274{
275 local wanted_prio
276 local daemon_prio
277 local daemon_list
278 local daemon_inst
279 local inst
280
281 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
282 daemon=${BASH_REMATCH[1]}
283 inst=${BASH_REMATCH[2]}
284 else
285 daemon="$2"
286 fi
287
288 wanted_prio=$1
289 daemon_list=${daemon:-$DAEMONS}
290
291 echo "Stopping FRRouting daemons (prio:$wanted_prio):"
292
293 for prio_i in `seq 10 -1 $wanted_prio`; do
294 for daemon_name in $daemon_list; do
295 eval daemon_prio=\${${daemon_name}:0:3}
296 daemon_inst=""
297 if [ $daemon_prio -eq $prio_i ]; then
298 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
299 if [ -n "$daemon_inst" ]; then
300 for i in ${daemon_inst}; do
301 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
302 stop "$daemon_name" "$inst"
303 elif [ x"$inst" == x ]; then
304 stop "$daemon_name" "$i"
305 fi
306 done
307 else
308 stop "$daemon_name"
309 fi
310 fi
311 done
312 done
313
314 if [ -z "$inst" ]; then
315 # Now stop other daemons that're prowling, coz the daemons file changed
316 echo "Stopping other FRRouting daemons"
317 if [ -n "$daemon" ]; then
318 eval "file_list_suffix="$V_PATH"/"$daemon*""
319 else
320 eval "file_list_suffix="$V_PATH/*""
321 fi
322 for pidfile in $file_list_suffix.pid; do
323 if [ -f "$pidfile" ]; then
324 filename=${pidfile##*/}
325 daemon=${filename%.*}
326 echo -n " $daemon"
327 killproc -p "$pidfile" "$daemon"
328 RETVAL=$?
329 [ $RETVAL -eq 0 ] && rm -f $lockfile
330 rm -f "$pidfile"
331 echo
332 fi
333 done
334 echo -n "Removing remaining .vty files"
335 for vtyfile in $file_list_suffix.vty; do
336 rm -rf "$vtyfile"
337 done
338 echo
339 fi
340}
341
342# Starts all daemons that have a higher level of priority than the given.
343# (technically if daemon_prio <= wanted_prio)
344start_prio()
345{
346 local wanted_prio
347 local daemon_prio
348 local daemon_list
349 local daemon_name
350 local daemon_inst
351 local inst
352
353 if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then
354 daemon=${BASH_REMATCH[1]}
355 inst=${BASH_REMATCH[2]}
356 else
357 daemon="$2"
358 fi
359
360 wanted_prio=$1
361 daemon_list=${daemon:-$DAEMONS}
362
363 echo "Starting FRRouting daemons (prio:$wanted_prio):"
364
365 for prio_i in `seq 1 $wanted_prio`; do
366 for daemon_name in $daemon_list; do
367 eval daemon_prio=\$${daemon_name}
368 daemon_inst=""
369 if [ $daemon_prio -eq $prio_i ]; then
370 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
371 if [ -n "$daemon_inst" ]; then
372 if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then
373 echo "Max instances supported is ${MAX_INSTANCES}. Aborting"
374 exit 1
375 fi
376 # Check if we're starting again by switching from single instance
377 # to MI version
378 if started "$daemon_name"; then
379 PIDFILE=`pidfile $daemon_name`
380 killproc -p "$PIDFILE" "$daemon_name"
381 rm -f `pidfile $1`
382 rm -f `vtyfile $1`
383 fi
384
385 for i in ${daemon_inst}; do
386 if [ -n "$inst" ] && [ "$i" == "$inst" ]; then
387 start "$daemon_name" "$inst"
388 elif [ x"$inst" == x ]; then
389 start "$daemon_name" "$i"
390 fi
391 done
392 else
393 # Check if we're starting again by switching from
394 # single instance to MI version
395 eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
396 for pidfile in $file_list_suffix.pid; do
397 if [ -f "$pidfile" ]; then
398 killproc -p "$pidfile" "$daemon_name"
399 rm -rf "$pidfile"
400 fi
401 done
402 for vtyfile in $file_list_suffix.vty; do
403 rm -rf "$vtyfile"
404 done
405
406 start "$daemon_name"
407 fi
408 fi
409 done
410 done
411}
412
413check_status()
414{
415 local daemon_name
416 local daemon_prio
417 local daemon_inst
418 local failed_status=0
419
420 if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then
421 daemon=${BASH_REMATCH[1]}
422 inst=${BASH_REMATCH[2]}
423 else
424 daemon="$1"
425 fi
426
427 daemon_list=${daemon:-$DAEMONS}
428
429 # Which daemons have been started?
430 for daemon_name in $daemon_list; do
431 eval daemon_prio=\$$daemon_name
432 if [ "$daemon_prio" -gt 0 ]; then
433 eval "daemon_inst=\${${daemon_name}_instances//,/ }"
434 if [ -n "$daemon_inst" ]; then
435 for i in ${daemon_inst}; do
436 if [ -n "$inst" -a "$inst" = "$i" ]; then
437 started "$1" "log" || failed_status=$?
438 elif [ -z "$inst" ]; then
439 started "$daemon_name-$i" "log" || failed_status=$?
440 fi
441 done
442 else
443 started "$daemon_name" "log" || failed_status=$?
444 fi
445 fi
446 done
447
448 # All daemons that need to have been started are up and running
449 return $failed_status
450}
451
452#########################################################
453# Main program #
454#########################################################
455
456# Config broken but script must exit silently.
457[ ! -r "$C_PATH/daemons" ] && exit 0
458
459# Load configuration
460. "$C_PATH/daemons"
461
462# Read configuration variable file if it is present
463[ -r /etc/sysconfig/frr ] && . /etc/sysconfig/frr
464
465MAX_INSTANCES=${MAX_INSTANCES:=5}
466
467# Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
468convert_daemon_prios
469
470if [ ! -d $V_PATH ]; then
471 echo "Creating $V_PATH"
472 mkdir -p $V_PATH
473 chown frr:frr $V_PATH
474 chmod 755 /$V_PATH
475fi
476
477if [ -n "$3" ] && [ "$3" != "all" ]; then
478 dmn="$2"-"$3"
479elif [ -n "$2" ] && [ "$2" != "all" ]; then
480 dmn="$2"
481fi
482
483case "$1" in
484 start)
485 # Try to load this necessary (at least for 2.6) module.
486 if [ -d /lib/modules/`uname -r` ] ; then
487 echo "Loading capability module if not yet done."
488 LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"
489 fi
490
491 # Start all daemons
492 cd $C_PATH/
493 if [ "$2" != "watchfrr" ]; then
494 start_prio 10 $dmn
495 fi
496 start_watchfrr
497 vtysh_b
498 ;;
499
500 1|2|3|4|5|6|7|8|9|10)
501 # Stop/start daemons for the appropriate priority level
502 stop_prio $1
503 start_prio $1
504 vtysh_b
505 ;;
506
507 stop|0)
508 # Stop all daemons at level '0' or 'stop'
509 stop_watchfrr
510 if [ "$dmn" != "watchfrr" ]; then
511 [ -n "${dmn}" ] && eval "${dmn/-/_}=0"
512 stop_prio 0 $dmn
513 fi
514
515 if [ -z "$dmn" -o "$dmn" = "zebra" ]; then
516 echo "Removing all routes made by zebra."
517 ip route flush proto zebra
651db60f
BR
518 # At least in CentOS/RHEL 6, iproute2 doesn't know
519 # about the new protocol names, so we have to flush them
520 # by number (it also doesn't support rt_protos.d
521 ip route flush proto 186
522 ip route flush proto 187
523 ip route flush proto 188
524 ip route flush proto 189
525 ip route flush proto 190
526 ip route flush proto 191
527 ip route flush proto 192
528 ip route flush proto 193
529 ip route flush proto 194
c2953ac5
MW
530 else
531 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
532 start_watchfrr
533 fi
534 ;;
535
536 reload)
537 # Just apply the commands that have changed, no restart necessary
6dc47763 538 if [ ! -x "$RELOAD_SCRIPT" ]; then
da4b95e7
MW
539 echo "frr-reload - reload not supported. Use restart or install frr-pythontools package"
540 exit 1
6dc47763 541 fi
c2953ac5 542 NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}"
6dc47763 543 if [ ! -r $NEW_CONFIG_FILE ]; then
da4b95e7
MW
544 echo "Unable to read configuration file $NEW_CONFIG_FILE. Only supporting integrated config"
545 exit 1
6dc47763 546 fi
c2953ac5
MW
547 echo "Applying only incremental changes to running configuration from frr.conf"
548 "$RELOAD_SCRIPT" --reload /etc/frr/frr.conf
549 exit $?
550 ;;
551
552 status)
553 check_status $dmn
554 exit $?
555 ;;
556
557 restart|force-reload)
558 $0 stop $dmn
559 sleep 1
560 $0 start $dmn
561 ;;
562
563 *)
564 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
565 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
566 echo " reload applies only modifications from the running config to all daemons."
567 echo " reload neither restarts starts any daemon nor starts any new ones."
568 echo " Read /usr/share/doc/frr/README.Debian for details."
569 exit 1
570 ;;
571esac
572
573exit 0