]> git.proxmox.com Git - mirror_frr.git/blob - redhat/frr.init
redhat: Add missing pimd & babels to startup scripts and config
[mirror_frr.git] / redhat / frr.init
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
28 PATH=/bin:/usr/bin:/sbin:/usr/sbin
29 D_PATH=/usr/lib/frr
30 C_PATH=/etc/frr
31 V_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!
36 DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd pimd ldpd nhrpd eigrpd babeld"
37 MAX_INSTANCES=5
38 RELOAD_SCRIPT=/usr/lib/frr/frr-reload.py
39
40 . /etc/init.d/functions
41
42 # Print the name of the pidfile.
43 pidfile()
44 {
45 echo "$V_PATH/$1.pid"
46 }
47
48 # Print the name of the vtysh.
49 vtyfile()
50 {
51 echo "$V_PATH/$1.vty"
52 }
53
54 # Check if daemon is started by using the pidfile.
55 started()
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.
67 vtysh_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
79 check_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.
108 start()
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.
161 stop()
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.
189 convert_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.
213 start_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.
265 stop_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)
273 stop_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)
344 start_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
413 check_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
465 MAX_INSTANCES=${MAX_INSTANCES:=5}
466
467 # Set priority of un-startable daemons to 'no' and substitute 'yes' to '0'
468 convert_daemon_prios
469
470 if [ ! -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
475 fi
476
477 if [ -n "$3" ] && [ "$3" != "all" ]; then
478 dmn="$2"-"$3"
479 elif [ -n "$2" ] && [ "$2" != "all" ]; then
480 dmn="$2"
481 fi
482
483 case "$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
518 else
519 [ -n "$dmn" ] && eval "${dmn/-/_}=0"
520 start_watchfrr
521 fi
522 ;;
523
524 reload)
525 # Just apply the commands that have changed, no restart necessary
526 if [ ! -x "$RELOAD_SCRIPT" ]; then
527 echo "frr-reload - reload not supported. Use restart or install frr-pythontools package"
528 exit 1
529 fi
530 NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}"
531 if [ ! -r $NEW_CONFIG_FILE ]; then
532 echo "Unable to read configuration file $NEW_CONFIG_FILE. Only supporting integrated config"
533 exit 1
534 fi
535 echo "Applying only incremental changes to running configuration from frr.conf"
536 "$RELOAD_SCRIPT" --reload /etc/frr/frr.conf
537 exit $?
538 ;;
539
540 status)
541 check_status $dmn
542 exit $?
543 ;;
544
545 restart|force-reload)
546 $0 stop $dmn
547 sleep 1
548 $0 start $dmn
549 ;;
550
551 *)
552 echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|<priority>} [daemon]"
553 echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5."
554 echo " reload applies only modifications from the running config to all daemons."
555 echo " reload neither restarts starts any daemon nor starts any new ones."
556 echo " Read /usr/share/doc/frr/README.Debian for details."
557 exit 1
558 ;;
559 esac
560
561 exit 0