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