From 10ea85ee45f4dd2ce818889616240ca3b1fd3c3e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 26 Oct 2018 21:02:22 +0200 Subject: [PATCH 1/7] tools/frr: get rid of the bash array and "bB" With a little shell-fu, this can actually be escaped properly. Signed-off-by: David Lamparter --- redhat/daemons | 2 +- redhat/frr.init | 42 ++++++++++++++------------ tools/etc/frr/daemons.conf | 3 +- tools/frr.in | 60 ++++++++++++++++++++------------------ 4 files changed, 56 insertions(+), 51 deletions(-) diff --git a/redhat/daemons b/redhat/daemons index c301a1c23a..7f3ff36df9 100644 --- a/redhat/daemons +++ b/redhat/daemons @@ -35,7 +35,7 @@ # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. # watchfrr_enable=yes -watchfrr_options=("-b_" "-r/usr/lib/frr/frr_restart_%s" "-s/usr/lib/frr/frr_start_%s" "-k/usr/lib/frr/frr_stop_%s") +watchfrr_options="-r '/usr/lib/frr/frr restart %s' -s '/usr/lib/frr/frr start %s' -k '/usr/lib/frr/frr stop %s'" # zebra=no bgpd=no diff --git a/redhat/frr.init b/redhat/frr.init index 47a92eed32..b59656adcd 100755 --- a/redhat/frr.init +++ b/redhat/frr.init @@ -107,22 +107,28 @@ check_daemon() # The Frr daemons creates the pidfile when starting. start() { + local dmn inst + dmn="$1" + inst="$2" + ulimit -n $MAX_FDS > /dev/null 2> /dev/null - if [ "$1" = "watchfrr" ]; then + if [ "$dmn" = "watchfrr" ]; then # We may need to restart watchfrr if new daemons are added and/or # removed - if started "$1" ; then + if started "$dmn" ; then stop watchfrr else # Echo only once. watchfrr is printed in the stop above - echo -n " $1" + echo -n " $dmn" fi if [ -e /var/run/frr/watchfrr.started ] ; then rm /var/run/frr/watchfrr.started fi - daemon --pidfile=`pidfile $1` "$D_PATH/$1" -d "${watchfrr_options[@]}" + # redhat /etc/init.d/functions daemon() re-expands args :( + # eval "set - $watchfrr_options" + daemon --pidfile=`pidfile $dmn` "$D_PATH/$dmn" -d "$watchfrr_options" RETVAL=$? [ $RETVAL -ne 0 ] && break for i in `seq 1 10`; @@ -135,25 +141,25 @@ start() fi done RETVAL=1 - elif [ -n "$2" ]; then - echo -n " $1-$2" - if ! check_daemon $1 $2 ; then + elif [ -n "$inst" ]; then + echo -n " $dmn-$inst" + if ! check_daemon $dmn $inst ; then echo -n " (binary does not exist)" return; fi - daemon --pidfile=`pidfile $1-$2` "$D_PATH/$1" -d `eval echo "$""$1""_options"` -n "$2" + daemon --pidfile=`pidfile $dmn-$inst` "$D_PATH/$dmn" -d `eval echo "$""$dmn""_options"` -n "$inst" RETVAL=$? else - echo -n " $1 " - if ! check_daemon $1; then + echo -n " $dmn " + if ! check_daemon $dmn; then echo " (binary does not exist)" return; fi - daemon --pidfile=`pidfile $1` "$D_PATH/$1" -d `eval echo "$""$1""_options"` + daemon --pidfile=`pidfile $dmn` "$D_PATH/$dmn" -d `eval echo "$""$dmn""_options"` RETVAL=$? fi echo - [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$1 + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$dmn return $RETVAL } @@ -223,11 +229,9 @@ start_watchfrr() fi # Check variable type - if ! declare -p watchfrr_options | grep -q '^declare \-a'; then - echo - echo "ERROR: The variable watchfrr_options from /etc/frr/daemons must be a BASH array!" - echo "ERROR: Please convert config file and restart!" - exit 1 + if declare -p watchfrr_options | grep -q '^declare \-a'; then + # old array support + watchfrr_options="${watchfrr_options[@]}" fi # Which daemons have been started? @@ -241,13 +245,13 @@ start_watchfrr() eval "inst_disable=\${${daemon_name}_${inst}}" if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then if check_daemon $daemon_name $inst; then - watchfrr_options+=("${daemon_name}-${inst}") + watchfrr_options="$watchfrr_options ${daemon_name}-${inst}" fi fi done else if check_daemon $daemon_name; then - watchfrr_options+=($daemon_name) + watchfrr_options="$watchfrr_options $daemon_name" fi fi found_one=1 diff --git a/tools/etc/frr/daemons.conf b/tools/etc/frr/daemons.conf index 94221301eb..1f608cfe08 100644 --- a/tools/etc/frr/daemons.conf +++ b/tools/etc/frr/daemons.conf @@ -24,8 +24,7 @@ fabricd_options=" --daemon -A 127.0.0.1" # The list of daemons to watch is automatically generated by the init script. watchfrr_enable=yes - -watchfrr_options=(-d -r /usr/lib/frr/frrbBrestartbB%s -s /usr/lib/frr/frrbBstartbB%s -k /usr/lib/frr/frrbBstopbB%s -b bB) +watchfrr_options="-d -r '/usr/lib/frr/frr restart %s' -s '/usr/lib/frr/frr start %s' -k '/usr/lib/frr/frr stop %s'" # If valgrind_enable is 'yes' the frr daemons will be started via valgrind. # The use case for doing so is tracking down memory leaks, etc in frr. diff --git a/tools/frr.in b/tools/frr.in index ec383bc5a0..a443191fd0 100755 --- a/tools/frr.in +++ b/tools/frr.in @@ -115,41 +115,45 @@ check_daemon() # The Frr daemons creates the pidfile when starting. start() { - ulimit -n $MAX_FDS - if [ "$1" = "watchfrr" ]; then + local dmn inst + dmn="$1" + inst="$2" + + ulimit -n $MAX_FDS > /dev/null 2> /dev/null + if [ "$dmn" = "watchfrr" ]; then # We may need to restart watchfrr if new daemons are added and/or # removed - if started "$1" ; then + if started "$dmn" ; then stop watchfrr else # Echo only once. watchfrr is printed in the stop above - echo -n " $1" + echo -n " $dmn" fi - + eval "set - $watchfrr_options" ${SSD} \ --start \ - --pidfile=`pidfile $1` \ - --exec "$D_PATH/$1" \ + --pidfile=`pidfile $dmn` \ + --exec "$D_PATH/$dmn" \ -- \ - "${watchfrr_options[@]}" + "$@" - elif [ -n "$2" ]; then - echo -n " $1-$2" - if ! check_daemon $1 $2 ; then + elif [ -n "$inst" ]; then + echo -n " $dmn-$inst" + if ! check_daemon $dmn $inst ; then echo -n " (binary does not exist)" return; fi ${SSD} \ --start \ - --pidfile=`pidfile $1-$2` \ - --exec "$D_PATH/$1" \ + --pidfile=`pidfile $dmn-$inst` \ + --exec "$D_PATH/$dmn" \ -- \ - `eval echo "$""$1""_options"` -n "$2" + `eval echo "$""$dmn""_options"` -n "$inst" else - if ! check_daemon $1; then + if ! check_daemon $dmn; then echo -n " (binary does not exist)" return; fi @@ -157,22 +161,22 @@ start() if [ "$valgrind_enable" = "yes" ]; then ${SSD} \ --start \ - --pidfile=`pidfile $1` \ + --pidfile=`pidfile $dmn` \ --exec "$valgrind" \ - -- --trace-children=no --leak-check=full --log-file=/var/log/frr/$1-valgrind.log $D_PATH/$1 \ - `eval echo "$""$1""_options"` + -- --trace-children=no --leak-check=full --log-file=/var/log/frr/$dmn-valgrind.log $D_PATH/$dmn \ + `eval echo "$""$dmn""_options"` else ${SSD} \ --start \ - --pidfile=`pidfile $1` \ - --exec "$D_PATH/$1" \ + --pidfile=`pidfile $dmn` \ + --exec "$D_PATH/$dmn" \ -- \ - `eval echo "$""$1""_options"` + `eval echo "$""$dmn""_options"` fi fi # Start the staticd automatically - if [ "$1" = "zebra" ]; then + if [ "$dmn" = "zebra" ]; then echo -n "starting staticd since zebra is running" if ! check_daemon staticd ; then echo -n " (binary does not exist)" @@ -269,11 +273,9 @@ start_watchfrr() fi # Check variable type - if ! declare -p watchfrr_options | grep -q '^declare \-a'; then - echo - echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!" - echo "ERROR: Please convert config file and restart!" - exit 1 + if declare -p watchfrr_options | grep -q '^declare \-a'; then + # old array support + watchfrr_options="${watchfrr_options[@]}" fi # Which daemons have been started? @@ -287,13 +289,13 @@ start_watchfrr() eval "inst_disable=\${${daemon_name}_${inst}}" if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then if check_daemon $daemon_name $inst; then - watchfrr_options+=("${daemon_name}-${inst}") + watchfrr_options="$watchfrr_options ${daemon_name}-${inst}" fi fi done else if check_daemon $daemon_name; then - watchfrr_options+=($daemon_name) + watchfrr_options="$watchfrr_options $daemon_name" fi fi found_one=1 From c0e5cb5271d1c547b5d789a10c9c973599335278 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 30 Nov 2018 17:55:42 +0100 Subject: [PATCH 2/7] watchfrr: don't wait around pointlessly at startup We were waiting for timers to expire even when we already know the status of all daemons. This delays startup for no good reason. Signed-off-by: David Lamparter --- watchfrr/watchfrr.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index e32bf3359b..95fa6c4aec 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -65,6 +65,7 @@ static bool watch_only = false; typedef enum { PHASE_NONE = 0, + PHASE_INIT, PHASE_STOPS_PENDING, PHASE_WAITING_DOWN, PHASE_ZEBRA_RESTART_PENDING, @@ -73,6 +74,7 @@ typedef enum { static const char *phase_str[] = { "None", + "Startup", "Stop jobs running", "Waiting for other daemons to come down", "Zebra restart job running", @@ -112,7 +114,7 @@ static struct global_state { int numpids; int numdown; /* # of daemons that are not UP or UNRESPONSIVE */ } gs = { - .phase = PHASE_NONE, + .phase = PHASE_INIT, .vtydir = frr_vtydir, .period = 1000 * DEFAULT_PERIOD, .timeout = DEFAULT_TIMEOUT, @@ -494,12 +496,12 @@ static int wakeup_init(struct thread *t_wakeup) dmn->t_wakeup = NULL; if (try_connect(dmn) < 0) { - SET_WAKEUP_DOWN(dmn); flog_err(EC_WATCHFRR_CONNECTION, "%s state -> down : initial connection attempt failed", dmn->name); dmn->state = DAEMON_DOWN; } + phase_check(); return 0; } @@ -773,9 +775,25 @@ static void set_phase(restart_phase_t new_phase) static void phase_check(void) { + struct daemon *dmn; + switch (gs.phase) { case PHASE_NONE: break; + + case PHASE_INIT: + for (dmn = gs.daemons; dmn; dmn = dmn->next) + if (dmn->state == DAEMON_INIT) + return; + + /* startup complete, everything out of INIT */ + gs.phase = PHASE_NONE; + for (dmn = gs.daemons; dmn; dmn = dmn->next) + if (dmn->state == DAEMON_DOWN) { + SET_WAKEUP_DOWN(dmn); + try_restart(dmn); + } + break; case PHASE_STOPS_PENDING: if (gs.numpids) break; @@ -980,8 +998,7 @@ static void watchfrr_init(int argc, char **argv) gs.numdown++; dmn->fd = -1; dmn->t_wakeup = NULL; - thread_add_timer_msec(master, wakeup_init, dmn, - 100 + (random() % 900), + thread_add_timer_msec(master, wakeup_init, dmn, 0, &dmn->t_wakeup); dmn->restart.interval = gs.min_restart_interval; *add = dmn; From 75f8b0e41b500b02675222515f3173c4effebdfe Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 30 Nov 2018 17:56:04 +0100 Subject: [PATCH 3/7] watchfrr: immediately try connecting after start When we make a call to (re)start some daemon(s), we can immediately try connecting to its VTY socket after the script completes. If the daemon started correctly, this will always succeed since the start script only returns after daemon startup is complete. Among other things, this reduces the delay to "startup complete" notification at initial watchfrr start. Signed-off-by: David Lamparter --- watchfrr/watchfrr.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index 95fa6c4aec..35a633b158 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -179,6 +179,7 @@ static int try_connect(struct daemon *dmn); static int wakeup_send_echo(struct thread *t_wakeup); static void try_restart(struct daemon *dmn); static void phase_check(void); +static void restart_done(struct daemon *dmn); static const char *progname; static void printhelp(FILE *target) @@ -335,6 +336,7 @@ static void sigchild(void) const char *name; const char *what; struct restart_info *restart; + struct daemon *dmn; switch (child = waitpid(-1, &status, WNOHANG)) { case -1: @@ -380,9 +382,18 @@ static void sigchild(void) zlog_warn( "%s %s process %d exited with non-zero status %d", what, name, (int)child, WEXITSTATUS(status)); - else + else { zlog_debug("%s %s process %d exited normally", what, name, (int)child); + + if (restart && restart != &gs.restart) { + dmn = container_of(restart, struct daemon, + restart); + restart_done(dmn); + } else if (restart) + for (dmn = gs.daemons; dmn; dmn = dmn->next) + restart_done(dmn); + } } else flog_err_sys( EC_LIB_SYSTEM_CALL, @@ -505,6 +516,18 @@ static int wakeup_init(struct thread *t_wakeup) return 0; } +static void restart_done(struct daemon *dmn) +{ + if (dmn->state != DAEMON_DOWN) { + zlog_warn("wtf?"); + return; + } + if (dmn->t_wakeup) + THREAD_OFF(dmn->t_wakeup); + if (try_connect(dmn) < 0) + SET_WAKEUP_DOWN(dmn); +} + static void daemon_down(struct daemon *dmn, const char *why) { if (IS_UP(dmn) || (dmn->state == DAEMON_INIT)) From af568444cba565370a978bdc61a43c024df913fd Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 30 Nov 2018 17:56:42 +0100 Subject: [PATCH 4/7] watchfrr: add status command Just to see WTF is going on inside watchfrr... Signed-off-by: David Lamparter --- watchfrr/watchfrr.c | 27 ++++++++++++++++++++++++++- watchfrr/watchfrr.h | 4 ++++ watchfrr/watchfrr_vty.c | 11 +++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index 35a633b158..e28da6db8c 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -73,7 +73,7 @@ typedef enum { } restart_phase_t; static const char *phase_str[] = { - "None", + "Idle", "Startup", "Stop jobs running", "Waiting for other daemons to come down", @@ -970,6 +970,31 @@ bool check_all_up(void) return true; } +void watchfrr_status(struct vty *vty) +{ + struct daemon *dmn; + struct timeval delay; + + vty_out(vty, "watchfrr global phase: %s\n", phase_str[gs.phase]); + if (gs.restart.pid) + vty_out(vty, " global restart running, pid %ld\n", + (long)gs.restart.pid); + + for (dmn = gs.daemons; dmn; dmn = dmn->next) { + vty_out(vty, " %-20s %s\n", dmn->name, state_str[dmn->state]); + if (dmn->restart.pid) + vty_out(vty, " restart running, pid %ld\n", + (long)dmn->restart.pid); + else if (dmn->state == DAEMON_DOWN && + time_elapsed(&delay, &dmn->restart.time)->tv_sec + < dmn->restart.interval) + vty_out(vty, " restarting in %ld seconds" + " (%lds backoff interval)\n", + dmn->restart.interval - delay.tv_sec, + dmn->restart.interval); + } +} + static void sigint(void) { zlog_notice("Terminating on signal"); diff --git a/watchfrr/watchfrr.h b/watchfrr/watchfrr.h index ee16846a1d..c5f54769bd 100644 --- a/watchfrr/watchfrr.h +++ b/watchfrr/watchfrr.h @@ -29,6 +29,10 @@ extern void watchfrr_vty_init(void); extern pid_t integrated_write_pid; extern void integrated_write_sigchld(int status); + +struct vty; +extern void watchfrr_status(struct vty *vty); + /* * Check if all daemons we are monitoring are in the DAEMON_UP state. * diff --git a/watchfrr/watchfrr_vty.c b/watchfrr/watchfrr_vty.c index 1bfc41f255..9b844d67f2 100644 --- a/watchfrr/watchfrr_vty.c +++ b/watchfrr/watchfrr_vty.c @@ -124,6 +124,16 @@ DEFUN_NOSH (show_debugging_watchfrr, return CMD_SUCCESS; } +DEFUN (show_watchfrr, + show_watchfrr_cmd, + "show watchfrr", + SHOW_STR + WATCHFRR_STR) +{ + watchfrr_status(vty); + return CMD_SUCCESS; +} + void integrated_write_sigchld(int status) { uint8_t reply[4] = {0, 0, 0, CMD_WARNING}; @@ -159,4 +169,5 @@ void watchfrr_vty_init(void) install_element(ENABLE_NODE, &config_write_integrated_cmd); install_element(ENABLE_NODE, &show_debugging_watchfrr_cmd); install_element(CONFIG_NODE, &show_debugging_watchfrr_cmd); + install_element(VIEW_NODE, &show_watchfrr_cmd); } From ea4d91bfbac01957a73d55f20bbe2c85ff8d0196 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 30 Nov 2018 21:40:39 +0100 Subject: [PATCH 5/7] debian/tools: new init script This separates the init script used for the system (and called in the systemd unit file) from the script that watchfrr uses to control daemons. Mixing these two caused the entire thing to become a rather huge spaghetti mess. Note that there is a behaviour change in that the new script always starts zebra regardless of zebra_enable. Side changes: - Ubuntu 12.04 removed from backports since it doesn't work anyway - zebra is always started regardless of zebra_enable. To disable FRR, the entire init script should be disabled through policy. - no-watchfrr operation is no longer supported by the scripts in the Debian packages. (This is intentional.) Signed-off-by: David Lamparter --- configure.ac | 3 + .../backports/ubuntu12.04/debian/control | 56 ---- .../backports/ubuntu12.04/debian/frr.install | 1 - .../backports/ubuntu12.04/debian/frr.postinst | 1 - .../backports/ubuntu12.04/debian/frr.postrm | 1 - debianpkg/backports/ubuntu12.04/debian/rules | 162 --------- .../ubuntu12.04/debian/source/format | 1 - debianpkg/backports/ubuntu12.04/exclude | 0 debianpkg/backports/ubuntu12.04/versionext | 1 - .../backports/ubuntu14.04/debian/frr.install | 1 - .../backports/ubuntu14.04/debian/frr.postinst | 38 --- .../backports/ubuntu14.04/debian/frr.postrm | 14 - debianpkg/backports/ubuntu14.04/debian/rules | 2 + debianpkg/rules | 2 +- debianpkg/subdir.am | 10 - redhat/frr.spec.in | 3 + tools/.gitignore | 3 + tools/etc/frr/daemons | 10 +- tools/etc/frr/daemons.conf | 47 +-- tools/frr.service | 7 +- tools/frrcommon.sh.in | 317 ++++++++++++++++++ tools/frrinit.sh.in | 90 +++++ tools/subdir.am | 4 + tools/watchfrr.sh.in | 33 ++ 24 files changed, 484 insertions(+), 323 deletions(-) delete mode 100644 debianpkg/backports/ubuntu12.04/debian/control delete mode 120000 debianpkg/backports/ubuntu12.04/debian/frr.install delete mode 120000 debianpkg/backports/ubuntu12.04/debian/frr.postinst delete mode 120000 debianpkg/backports/ubuntu12.04/debian/frr.postrm delete mode 100755 debianpkg/backports/ubuntu12.04/debian/rules delete mode 100644 debianpkg/backports/ubuntu12.04/debian/source/format delete mode 100644 debianpkg/backports/ubuntu12.04/exclude delete mode 100644 debianpkg/backports/ubuntu12.04/versionext delete mode 100644 debianpkg/backports/ubuntu14.04/debian/frr.postinst delete mode 100644 debianpkg/backports/ubuntu14.04/debian/frr.postrm create mode 100644 tools/frrcommon.sh.in create mode 100644 tools/frrinit.sh.in create mode 100644 tools/watchfrr.sh.in diff --git a/configure.ac b/configure.ac index 09d57ab0f2..f7328988b2 100755 --- a/configure.ac +++ b/configure.ac @@ -2180,6 +2180,9 @@ AC_CONFIG_FILES([ AC_CONFIG_FILES([vtysh/extract.pl], [chmod +x vtysh/extract.pl]) AC_CONFIG_FILES([tools/frr], [chmod +x tools/frr]) +AC_CONFIG_FILES([tools/watchfrr.sh], [chmod +x tools/watchfrr.sh]) +AC_CONFIG_FILES([tools/frrinit.sh], [chmod +x tools/frrinit.sh]) +AC_CONFIG_FILES([tools/frrcommon.sh]) AC_CONFIG_COMMANDS([lib/route_types.h], [ dst="${ac_abs_top_builddir}/lib/route_types.h" diff --git a/debianpkg/backports/ubuntu12.04/debian/control b/debianpkg/backports/ubuntu12.04/debian/control deleted file mode 100644 index 9bae348840..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/control +++ /dev/null @@ -1,56 +0,0 @@ -Source: frr -Section: net -Priority: optional -Maintainer: Nobody -Uploaders: Nobody -XSBC-Original-Maintainer: -Build-Depends: debhelper (>= 7.0.50~), libncurses5-dev, libreadline-dev, texlive-latex-base, texlive-generic-recommended, libpam0g-dev | libpam-dev, libcap-dev, texinfo (>= 4.7), imagemagick, ghostscript, groff, autotools-dev, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson0, libjson0-dev, pkg-config, python (>= 2.7), python-ipaddr -Standards-Version: 3.9.6 -Homepage: http://www.frrouting.org/ -XS-Testsuite: autopkgtest - -Package: frr -Architecture: any -Depends: ${shlibs:Depends}, logrotate (>= 3.2-11), ${misc:Depends} -Pre-Depends: adduser -Conflicts: zebra, zebra-pj, quagga -Replaces: zebra, zebra-pj -Suggests: snmpd -Description: BGP/OSPF/RIP/RIPng/ISIS/PIM/LDP routing daemon forked from Quagga - FRR is free software which manages TCP/IP based routing protocols. - It supports BGP4, BGP4+, OSPFv2, OSPFv3, IS-IS, RIPv1, RIPv2, RIPng, - PIM and LDP as well as the IPv6 versions of these. - . - FRR is a fork of Quagga with an open community model. The main git - lives on https://github.com/frrouting/frr.git - -Package: frr-dbg -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, frr (= ${binary:Version}) -Priority: extra -Section: debug -Description: BGP/OSPF/RIP/RIPng/ISIS/PIM/LDP routing daemon (debug symbols) - This package provides debugging symbols for all binary packages built - from frr source package. It's highly recommended to have this package - installed before reporting any FRR crashes to either FRR developers or - Debian package maintainers. - -Package: frr-doc -Section: net -Architecture: all -Depends: ${misc:Depends} -Suggests: frr -Description: documentation files for FRR - This package includes info files for frr, a free software which manages - TCP/IP based routing protocols. It supports BGP4, BGP4+, OSPFv2, OSPFv3, - IS-IS, RIPv1, RIPv2, RIPng, PIM and LDP as well as the IPv6 versions of these. - -Package: frr-pythontools -Section: net -Architecture: all -Depends: ${misc:Depends}, frr (= ${binary:Version}), python (>= 2.7), python-ipaddr -Description: BGP/OSPF/RIP/RIPng/ISIS/PIM/LDP routing daemon (Python Tools) - This package includes info files for frr, a free software which manages - TCP/IP based routing protocols. It supports BGP4, BGP4+, OSPFv2, OSPFv3, - IS-IS, RIPv1, RIPv2, RIPng, PIM and LDP as well as the IPv6 versions of these. - diff --git a/debianpkg/backports/ubuntu12.04/debian/frr.install b/debianpkg/backports/ubuntu12.04/debian/frr.install deleted file mode 120000 index 83ecca5958..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/frr.install +++ /dev/null @@ -1 +0,0 @@ -../../ubuntu14.04/debian/frr.install \ No newline at end of file diff --git a/debianpkg/backports/ubuntu12.04/debian/frr.postinst b/debianpkg/backports/ubuntu12.04/debian/frr.postinst deleted file mode 120000 index eb98053c7b..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/frr.postinst +++ /dev/null @@ -1 +0,0 @@ -../../ubuntu14.04/debian/frr.postinst \ No newline at end of file diff --git a/debianpkg/backports/ubuntu12.04/debian/frr.postrm b/debianpkg/backports/ubuntu12.04/debian/frr.postrm deleted file mode 120000 index 4f4380872f..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/frr.postrm +++ /dev/null @@ -1 +0,0 @@ -../../ubuntu14.04/debian/frr.postrm \ No newline at end of file diff --git a/debianpkg/backports/ubuntu12.04/debian/rules b/debianpkg/backports/ubuntu12.04/debian/rules deleted file mode 100755 index 7495db89cb..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/rules +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/make -f - -# FRRouting Configuration options -###################################### -# -# WANT_xxxx --> Set to 1 for enable, 0 for disable -# The following are the defaults. They can be overridden by setting a -# env variable to a different value - -WANT_LDP ?= 1 -WANT_PIM ?= 1 -WANT_OSPFAPI ?= 1 -WANT_BGP_VNC ?= 1 -WANT_CUMULUS_MODE ?= 0 -WANT_MULTIPATH ?= 1 -WANT_SNMP ?= 0 - -# NOTES: -# -# If multipath is enabled (WANT_MULTIPATH=1), then set number of multipaths here -# Please be aware that 0 is NOT disabled, but treated as unlimited - -MULTIPATH ?= 256 - -# Set the following to the value required (or leave alone for the default below) -# WANT_FRR_USER is used for the username and groupname of the FRR user account - -WANT_FRR_USER ?= frr -WANT_FRR_VTY_GROUP ?= frrvty - -# Don't build PDF docs by default -GENERATE_PDF ?= 0 - -# -#################################### - -export DH_VERBOSE=1 -export DEB_BUILD_MAINT_OPTIONS = hardening=+all -export DH_OPTIONS=-v - -ifeq ($(WANT_SNMP), 1) - USE_SNMP=--enable-snmp - $(warning "DEBIAN: SNMP enabled, sorry for your inconvenience") -else - USE_SNMP=--disable-snmp - $(warning "DEBIAN: SNMP disabled, see README.Debian") -endif - -ifeq ($(WANT_LDP), 1) - USE_LDP=--enable-ldpd -else - USE_LDP=--disable-ldpd -endif - -ifeq ($(WANT_PIM), 1) - USE_PIM=--enable-pimd -else - USE_PIM=--disable-pimd -endif - -ifeq ($(WANT_OSPFAPI), 1) - USE_OSPFAPI=--enable-ospfapi=yes -else - USE_OSPFAPI=--enable-ospfapi=no -endif - -ifeq ($(WANT_BGP_VNC), 1) - USE_BGP_VNC=--enable-bgp-vnc=yes -else - USE_BGP_VNC=--enable-bgp-vnc=no -endif - -USE_FRR_USER=--enable-user=$(WANT_FRR_USER) -USE_FRR_GROUP=--enable-group=$(WANT_FRR_USER) -USE_FRR_VTY_GROUP=--enable-vty-group=$(WANT_FRR_VTY_GROUP) - -ifeq ($(WANT_MULTIPATH), 1) - USE_MULTIPATH=--enable-multipath=$(MULTIPATH) -else - USE_MULTIPATH=--disable-multipath -endif - -ifeq ($(WANT_CUMULUS_MODE), 1) - USE_CUMULUS=--enable-cumulus=yes -else - USE_CUMULUS=--enable-cumulus=no -endif - -ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) - DEBIAN_JOBS := $(subst parallel=,,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) -endif - -ifdef DEBIAN_JOBS -MAKEFLAGS += -j$(DEBIAN_JOBS) -endif - -%: - dh $@ --with=autoreconf --parallel --dbg-package=frr-dbg --list-missing - -override_dh_auto_configure: - # Frr needs /proc to check some BSD vs Linux specific stuff. - # Else it fails with an obscure error message pointing out that - # IPCTL_FORWARDING is an undefined symbol which is not very helpful. - @if ! [ -d /proc/1 ]; then \ - echo "./configure needs a mounted /proc"; \ - exit 1; \ - fi - - if ! [ -e config.status ]; then \ - dh_auto_configure -- \ - --enable-exampledir=/usr/share/doc/frr/examples/ \ - --localstatedir=/var/run/frr \ - --sbindir=/usr/lib/frr \ - --sysconfdir=/etc/frr \ - $(USE_SNMP) \ - $(USE_OSPFAPI) \ - $(USE_MULTIPATH) \ - $(USE_LDP) \ - --enable-fpm \ - $(USE_FRR_USER) $(USE_FRR_GROUP) \ - $(USE_FRR_VTY_GROUP) \ - --enable-configfile-mask=0640 \ - --enable-logfile-mask=0640 \ - --with-libpam \ - --enable-systemd=no \ - --enable-poll=yes \ - $(USE_CUMULUS) \ - $(USE_PIM) \ - --disable-bfdd \ - --enable-dependency-tracking \ - $(USE_BGP_VNC) \ - $(shell dpkg-buildflags --export=configure); \ - fi - -override_dh_auto_build: -ifeq ($(GENERATE_PDF), 1) - dh_auto_build -- -C doc pdf -endif - rm -vf doc/user/_build/texinfo/frr.info - dh_auto_build -- -C doc info - -override_dh_auto_test: - -override_dh_auto_install: - dh_auto_install - - # installed in frr-pythontools - rm debian/tmp/usr/lib/frr/frr-reload.py - - # cleaning up the info dir - rm -f debian/tmp/usr/share/info/dir* - - # install config files - mkdir -p debian/tmp/etc/frr/ - perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample* - - # leftover from previously shipping SMUX client OID MIB - mkdir -p debian/tmp/usr/share/snmp/mibs - - # cleaning .la files - sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la - sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/frr/modules/*.la diff --git a/debianpkg/backports/ubuntu12.04/debian/source/format b/debianpkg/backports/ubuntu12.04/debian/source/format deleted file mode 100644 index 163aaf8d82..0000000000 --- a/debianpkg/backports/ubuntu12.04/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/debianpkg/backports/ubuntu12.04/exclude b/debianpkg/backports/ubuntu12.04/exclude deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/debianpkg/backports/ubuntu12.04/versionext b/debianpkg/backports/ubuntu12.04/versionext deleted file mode 100644 index 159e2e4160..0000000000 --- a/debianpkg/backports/ubuntu12.04/versionext +++ /dev/null @@ -1 +0,0 @@ --1~ubuntu12.04+1 diff --git a/debianpkg/backports/ubuntu14.04/debian/frr.install b/debianpkg/backports/ubuntu14.04/debian/frr.install index 199d264f1a..7fb81c44a0 100644 --- a/debianpkg/backports/ubuntu14.04/debian/frr.install +++ b/debianpkg/backports/ubuntu14.04/debian/frr.install @@ -3,7 +3,6 @@ usr/bin/vtysh usr/bin/mtracebis usr/include/frr/ usr/lib/ -tools/frr etc/init.d/ usr/share/doc/frr/ usr/share/snmp/mibs/ usr/share/yang/ diff --git a/debianpkg/backports/ubuntu14.04/debian/frr.postinst b/debianpkg/backports/ubuntu14.04/debian/frr.postinst deleted file mode 100644 index 5a14e510cd..0000000000 --- a/debianpkg/backports/ubuntu14.04/debian/frr.postinst +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -e - -###################### -PASSWDFILE=/etc/passwd -GROUPFILE=/etc/group - -frruid=`egrep "^frr:" $PASSWDFILE | awk -F ":" '{ print $3 }'` -frrgid=`egrep "^frr:" $GROUPFILE | awk -F ":" '{ print $3 }'` -frrvtygid=`egrep "^frrvty:" $GROUPFILE | awk -F ":" '{ print $3 }'` - -[ -n ${frruid} ] || (echo "No uid for frr in ${PASSWDFILE}" && /bin/false) -[ -n ${frrgid} ] || (echo "No gid for frr in ${GROUPFILE}" && /bin/false) -[ -n ${frrVTYgid} ] || (echo "No gid for frrvty in ${GROUPFILE}" && /bin/false) - -chown -R ${frruid}:${frrgid} /etc/frr -touch /etc/frr/vtysh.conf -chgrp ${frrvtygid} /etc/frr/vtysh* -chmod 644 /etc/frr/* - -ENVIRONMENTFILE=/etc/environment -if ! egrep --quiet '^VTYSH_PAGER=' ${ENVIRONMENTFILE}; then - echo "VTYSH_PAGER=/bin/cat" >> ${ENVIRONMENTFILE} -fi -################################################## - -if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi -${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"} - -# This is most likely due to the answer "no" to the "really stop the server" -# question in the prerm script. -if [ "$1" = "abort-upgrade" ]; then - exit 0 -fi - -update-rc.d frr defaults > /dev/null - -#DEBHELPER# - diff --git a/debianpkg/backports/ubuntu14.04/debian/frr.postrm b/debianpkg/backports/ubuntu14.04/debian/frr.postrm deleted file mode 100644 index 48c23321f7..0000000000 --- a/debianpkg/backports/ubuntu14.04/debian/frr.postrm +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -e - -if [ -n "$DEBIAN_SCRIPT_DEBUG" ]; then set -v -x; DEBIAN_SCRIPT_TRACE=1; fi -${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*"} -# set -u not because of debhelper - -update-rc.d -f frr remove >> /dev/null - -if [ "$1" = "purge" ]; then - rm -rf /etc/frr /var/run/frr /var/log/frr - userdel frr >/dev/null 2>&1 || true -fi - -#DEBHELPER# diff --git a/debianpkg/backports/ubuntu14.04/debian/rules b/debianpkg/backports/ubuntu14.04/debian/rules index 291233c147..21b442d85a 100755 --- a/debianpkg/backports/ubuntu14.04/debian/rules +++ b/debianpkg/backports/ubuntu14.04/debian/rules @@ -178,6 +178,8 @@ override_dh_auto_test: override_dh_auto_install: dh_auto_install + cp tools/frrinit.sh debian/frr.init + # installed in frr-pythontools rm debian/tmp/usr/lib/frr/frr-reload.py diff --git a/debianpkg/rules b/debianpkg/rules index 7cdb8fbaf7..12d6c3545c 100755 --- a/debianpkg/rules +++ b/debianpkg/rules @@ -171,7 +171,7 @@ override_dh_systemd_enable: # backports SRCPKG = frr -KNOWN_BACKPORTS = debian8 debian9 ubuntu12.04 ubuntu14.04 ubuntu16.04 ubuntu17.10 ubuntu18.04 +KNOWN_BACKPORTS = debian8 debian9 ubuntu14.04 ubuntu16.04 ubuntu17.10 ubuntu18.04 DEBIAN_VERSION := $(shell dh_testdir && \ dpkg-parsechangelog -c1 < debian/changelog | \ sed -rn 's/^Version: ?//p') diff --git a/debianpkg/subdir.am b/debianpkg/subdir.am index b6251962b7..af17e4642a 100644 --- a/debianpkg/subdir.am +++ b/debianpkg/subdir.am @@ -23,18 +23,8 @@ EXTRA_DIST += \ debianpkg/backports/debian9/debian/source/format \ debianpkg/backports/debian9/exclude \ debianpkg/backports/debian9/versionext \ - debianpkg/backports/ubuntu12.04/debian/control \ - debianpkg/backports/ubuntu12.04/debian/frr.install \ - debianpkg/backports/ubuntu12.04/debian/frr.postinst \ - debianpkg/backports/ubuntu12.04/debian/frr.postrm \ - debianpkg/backports/ubuntu12.04/debian/rules \ - debianpkg/backports/ubuntu12.04/debian/source/format \ - debianpkg/backports/ubuntu12.04/exclude \ - debianpkg/backports/ubuntu12.04/versionext \ debianpkg/backports/ubuntu14.04/debian/control \ debianpkg/backports/ubuntu14.04/debian/frr.install \ - debianpkg/backports/ubuntu14.04/debian/frr.postinst \ - debianpkg/backports/ubuntu14.04/debian/frr.postrm \ debianpkg/backports/ubuntu14.04/debian/rules \ debianpkg/backports/ubuntu14.04/debian/source/format \ debianpkg/backports/ubuntu14.04/exclude \ diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index d2da06faa6..7a6344aa4c 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -637,6 +637,9 @@ fi %config(noreplace) %{_sysconfdir}/pam.d/frr %config(noreplace) %{_sysconfdir}/logrotate.d/frr %{_sbindir}/frr-reload +%{_sbindir}/frrcommon.sh +%{_sbindir}/frrinit.sh +%{_sbindir}/watchfrr.sh %files contrib diff --git a/tools/.gitignore b/tools/.gitignore index c23322c4c6..85dae7fd36 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -3,3 +3,6 @@ /gen_yang_deviations /permutations /ssd +/watchfrr.sh +/frrinit.sh +/frrcommon.sh diff --git a/tools/etc/frr/daemons b/tools/etc/frr/daemons index 1514082e90..3f513bf618 100644 --- a/tools/etc/frr/daemons +++ b/tools/etc/frr/daemons @@ -1,11 +1,5 @@ # This file tells the frr package which daemons to start. # -# Entries are in the format: =(yes|no|priority) -# 0, "no" = disabled -# 1, "yes" = highest priority -# 2 .. 10 = lower priorities -# Read /usr/share/doc/frr/README.Debian for details. -# # Sample configurations for these daemons can be found in # /usr/share/doc/frr/examples/. # @@ -18,10 +12,8 @@ # When using "vtysh" such a config file is also needed. It should be owned by # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. # -# The watchfrr daemon is always started. Per default in monitoring-only but -# that can be changed via /etc/frr/daemons.conf. +# The watchfrr and zebra daemons are always started. # -zebra=no bgpd=no ospfd=no ospf6d=no diff --git a/tools/etc/frr/daemons.conf b/tools/etc/frr/daemons.conf index 1f608cfe08..02a785c87a 100644 --- a/tools/etc/frr/daemons.conf +++ b/tools/etc/frr/daemons.conf @@ -4,29 +4,30 @@ # Check /etc/pam.d/frr if you intend to use "vtysh"! # vtysh_enable=yes -zebra_options=" -s 90000000 --daemon -A 127.0.0.1" -bgpd_options=" --daemon -A 127.0.0.1" -ospfd_options=" --daemon -A 127.0.0.1" -ospf6d_options=" --daemon -A ::1" -ripd_options=" --daemon -A 127.0.0.1" -ripngd_options=" --daemon -A ::1" -isisd_options=" --daemon -A 127.0.0.1" -pimd_options=" --daemon -A 127.0.0.1" -ldpd_options=" --daemon -A 127.0.0.1" -nhrpd_options=" --daemon -A 127.0.0.1" -eigrpd_options=" --daemon -A 127.0.0.1" -babeld_options=" --daemon -A 127.0.0.1" -sharpd_options=" --daemon -A 127.0.0.1" -pbrd_options=" --daemon -A 127.0.0.1" -staticd_options=" --daemon -A 127.0.0.1" -bfdd_options=" --daemon -A 127.0.0.1" -fabricd_options=" --daemon -A 127.0.0.1" +zebra_options=" -A 127.0.0.1 -s 90000000" +bgpd_options=" -A 127.0.0.1" +ospfd_options=" -A 127.0.0.1" +ospf6d_options=" -A ::1" +ripd_options=" -A 127.0.0.1" +ripngd_options=" -A ::1" +isisd_options=" -A 127.0.0.1" +pimd_options=" -A 127.0.0.1" +ldpd_options=" -A 127.0.0.1" +nhrpd_options=" -A 127.0.0.1" +eigrpd_options=" -A 127.0.0.1" +babeld_options=" -A 127.0.0.1" +sharpd_options=" -A 127.0.0.1" +pbrd_options=" -A 127.0.0.1" +staticd_options="-A 127.0.0.1" +bfdd_options=" -A 127.0.0.1" +fabricd_options="-A 127.0.0.1" # The list of daemons to watch is automatically generated by the init script. -watchfrr_enable=yes -watchfrr_options="-d -r '/usr/lib/frr/frr restart %s' -s '/usr/lib/frr/frr start %s' -k '/usr/lib/frr/frr stop %s'" +watchfrr_options="-r '/usr/lib/frr/watchfrr.sh restart %s' -s '/usr/lib/frr/watchfrr.sh start %s' -k '/usr/lib/frr/watchfrr.sh stop %s'" -# If valgrind_enable is 'yes' the frr daemons will be started via valgrind. -# The use case for doing so is tracking down memory leaks, etc in frr. -valgrind_enable=no -valgrind=/usr/bin/valgrind +# for debugging purposes, you can specify a "wrap" command to start instead +# of starting the daemon directly, e.g. to use valgrind on ospfd: +# ospfd_wrap="/usr/bin/valgrind" +# or you can use "all_wrap" for all daemons, e.g. to use perf record: +# all_wrap="/usr/bin/perf record --call-graph -" +# the normal daemon command is added to this at the end. diff --git a/tools/frr.service b/tools/frr.service index 5f44274ec3..03112bd7cd 100644 --- a/tools/frr.service +++ b/tools/frr.service @@ -5,7 +5,6 @@ OnFailure=heartbeat-failed@%n.service [Service] Nice=-5 -EnvironmentFile=/etc/default/frr Type=forking NotifyAccess=all StartLimitInterval=3m @@ -15,8 +14,8 @@ WatchdogSec=60s RestartSec=5 Restart=on-abnormal LimitNOFILE=1024 -ExecStart=/usr/lib/frr/frr start -ExecStop=/usr/lib/frr/frr stop -ExecReload=/usr/lib/frr/frr-reload +ExecStart=/usr/lib/frr/frrinit.sh start +ExecStop=/usr/lib/frr/frrinit.sh stop +ExecReload=/usr/lib/frr/frrinit.sh reload [Install] WantedBy=network-online.target diff --git a/tools/frrcommon.sh.in b/tools/frrcommon.sh.in new file mode 100644 index 0000000000..7278e3f9df --- /dev/null +++ b/tools/frrcommon.sh.in @@ -0,0 +1,317 @@ +#!/bin/sh +# +# This is a "library" of sorts for use by the other FRR shell scripts. It +# has most of the daemon start/stop logic, but expects the following shell +# functions/commands to be provided by the "calling" script: +# +# log_success_msg +# log_warning_msg +# log_failure_msg +# +# (coincidentally, these are LSB standard functions.) +# +# Sourcing this file in a shell script will load FRR config variables but +# not perform any action. Note there is an "exit 1" if the main config +# file does not exist. +# +# This script should be installed in @CFG_SBIN@/frrcommon.sh + +PATH=/bin:/usr/bin:/sbin:/usr/sbin +D_PATH="@CFG_SBIN@" # /usr/lib/frr +C_PATH="@CFG_SYSCONF@" # /etc/frr +V_PATH="@CFG_STATE@" # /var/run/frr +VTYSH="@vtysh_bin@" # /usr/bin/vtysh +FRR_USER="@enable_user@" # frr +FRR_GROUP="@enable_group@" # frr +FRR_VTY_GROUP="@enable_vty_group@" # frrvty + +# ORDER MATTERS FOR $DAEMONS! +# - keep zebra first +# - watchfrr does NOT belong in this list + +DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd" +RELOAD_SCRIPT="$D_PATH/frr-reload.py" + +# +# general helpers +# + +debug() { + [ -n "$watchfrr_debug" ] || return 0 + + printf '%s %s(%s):' "`date +%Y-%m-%dT%H:%M:%S.%N`" "$0" $$ >&2 + # this is to show how arguments are split regarding whitespace & co. + # (e.g. for use with `debug "message" "$@"`) + while [ $# -gt 0 ]; do + printf ' "%s"' "$1" >&2 + shift + done + printf '\n' >&2 +} + +chownfrr() { + [ -n "$FRR_USER" ] && chown "$FRR_USER" "$1" + [ -n "$FRR_GROUP" ] && chgrp "$FRR_GROUP" "$1" +} + +vtysh_b () { + [ "$1" = "watchfrr" ] && return 0 + [ -r "$C_PATH/frr.conf" ] || return 0 + if [ -n "$1" ]; then + "$VTYSH" -b -n -d "$1" + else + "$VTYSH" -b -n + fi +} + +daemon_inst() { + # note this sets global variables ($dmninst, $daemon, $inst) + dmninst="$1" + daemon="${dmninst%:*}" + inst="" + [ "$daemon" != "$dmninst" ] && inst="${dmninst#*:}" +} + +daemon_list() { + # note $1 and $2 specify names for global variables to be set + local enabled disabled evar dvar + enabled="" + disabled="" + evar="$1" + dvar="$2" + + for daemon in $DAEMONS; do + eval cfg=\$$daemon + eval inst=\$${daemon}_instances + [ "$daemon" = zebra ] && cfg=yes + if [ -n "$cfg" -a "$cfg" != "no" -a "$cfg" != "0" ]; then + debug "$daemon enabled" + enabled="$enabled $daemon" + if [ -n "$inst" ]; then + debug "$daemon multi-instance $inst" + for i in $inst; do + enabled="$enabled $daemon:$inst" + done + fi + else + debug "$daemon disabled" + disabled="$disabled $daemon" + fi + done + + enabled="${enabled# }" + disabled="${disabled# }" + [ -z "$evar" ] && echo "$enabled" + [ -n "$evar" ] && eval $evar="\"$enabled\"" + [ -n "$dvar" ] && eval $dvar="\"$disabled\"" +} + +# +# individual daemon management +# + +daemon_prep() { + local daemon inst cfg + daemon="$1" + inst="$2" + [ "$daemon" = "watchfrr" ] && return 0 + [ -x "$D_PATH/$daemon" ] || { + log_failure_msg "cannot start $daemon${inst:+ (instance $inst)}: daemon binary not installed\n" + return 1 + } + [ -r "$C_PATH/frr.conf" ] && return 0 + + cfg="$C_PATH/$daemon${inst:+-$inst}.conf" + if [ ! -r "$cfg" ]; then + touch "$cfg" + chownfrr "$cfg" + fi + return 0 +} + +daemon_start() { + local dmninst daemon inst args instopt wrap bin + daemon_inst "$1" + + ulimit -n $MAX_FDS > /dev/null 2> /dev/null + daemon_prep "$daemon" "$inst" || return 1 + + eval wrap="\$${daemon}_wrap" + bin="$D_PATH/$daemon" + instopt="${inst:+-n $inst}" + eval args="\$${daemon}_options" + + if eval "$all_wrap $wrap $bin -d $instopt $args"; then + log_success_msg "Started $dmninst" + vtysh_b "$daemon" + else + log_failure_msg "Failed to start $dmninst!" + fi +} + +daemon_stop() { + local dmninst daemon inst pidfile vtyfile pid cnt fail + daemon_inst "$1" + + pidfile="$V_PATH/$daemon${inst:+-$inst}.pid" + vtyfile="$V_PATH/$daemon${inst:+-$inst}.vty" + + [ -r "$pidfile" ] || fail="pid file not found" + [ -z "$fail" ] && pid="`cat \"$pidfile\"`" + [ -z "$fail" -a -z "$pid" ] && fail="pid file is empty" + [ -n "$fail" ] || kill -0 "$pid" 2>/dev/null || fail="pid $pid not running" + + if [ -n "$fail" ]; then + log_failure_msg "Cannot stop $dmninst: $fail" + return 1 + fi + + debug "kill -2 $pid" + kill -2 "$pid" + cnt=1200 + while kill -0 "$pid" 2>/dev/null; do + sleep .1 + [ $(( cnt -= 1 )) -gt 0 ] || break + done + if kill -0 "$pid" 2>/dev/null; then + log_failure_msg "Failed to stop $dmninst, pid $pid still running" + still_running=1 + return 1 + else + log_success_msg "Stopped $dmninst" + rm -f "$pidfile" + return 0 + fi +} + +daemon_status() { + local dmninst daemon inst pidfile pid fail + daemon_inst "$1" + + pidfile="$V_PATH/$daemon${inst:+-$inst}.pid" + + [ -r "$pidfile" ] || return 3 + pid="`cat \"$pidfile\"`" + [ -z "$pid" ] && return 1 + kill -0 "$pid" 2>/dev/null || return 1 + return 0 +} + +print_status() { + daemon_status "$1" + rv=$? + if [ "$rv" -eq 0 ]; then + log_success_msg "Status of $1: running" + else + log_failure_msg "Status of $1: FAILED" + fi + return $rv +} + +# +# all-daemon commands +# + +all_start() { + daemon_list daemons + for dmninst in $daemons; do + daemon_start "$dmninst" + done +} + +all_stop() { + local pids reversed + + daemon_list daemons disabled + [ "$1" = "--reallyall" ] && daemons="$daemons $disabled" + + reversed="" + for dmninst in $daemons; do + reversed="$dmninst $reversed" + done + + for dmninst in $reversed; do + daemon_stop "$dmninst" & + pids="$pids $!" + done + for pid in $pids; do + wait $pid + done +} + +all_status() { + local fail + + daemon_list daemons + fail=0 + for dmninst in $daemons; do + print_status "$dmninst" || fail=1 + done + return $fail +} + +# +# config sourcing +# + +load_old_config() { + oldcfg="$1" + [ -r "$oldcfg" ] || return 0 + [ -s "$oldcfg" ] || return 0 + grep -v '^[[:blank:]]*\(#\|$\)' "$oldcfg" > /dev/null || return 0 + + log_warning_msg "Reading deprecated $oldcfg. Please move its settings to $C_PATH/daemons and remove it." + + # save off settings from daemons for the OR below + for dmn in $DAEMONS; do eval "_new_$dmn=\${$dmn:-no}"; done + + . "$oldcfg" + + # OR together the daemon enabling options between config files + for dmn in $DAEMONS; do eval "test \$_new_$dmn != no && $dmn=\$_new_$dmn; unset _new_$dmn"; done +} + +[ -r "$C_PATH/daemons" ] || { + log_failure_msg "cannot run $@: $C_PATH/daemons does not exist\n" + exit 1 +} +. "$C_PATH/daemons" + +load_old_config "$C_PATH/daemons.conf" +load_old_config "/etc/default/frr" +load_old_config "/etc/sysconfig/frr" + +# +# other defaults and dispatch +# + +frrcommon_main() { + local cmd + + debug "frrcommon_main" "$@" + + cmd="$1" + shift + + if [ "$1" = "all" -o -z "$1" ]; then + case "$cmd" in + start) all_start;; + stop) all_stop;; + restart) + all_stop + all_start + ;; + *) $cmd "$@";; + esac + else + case "$cmd" in + start) daemon_start "$@";; + stop) daemon_stop "$@";; + restart) + daemon_stop "$@" + daemon_start "$@" + ;; + *) $cmd "$@";; + esac + fi +} diff --git a/tools/frrinit.sh.in b/tools/frrinit.sh.in new file mode 100644 index 0000000000..3dddf5bd44 --- /dev/null +++ b/tools/frrinit.sh.in @@ -0,0 +1,90 @@ +#!/bin/sh +# +### BEGIN INIT INFO +# Provides: frr +# Required-Start: $local_fs $network $remote_fs $syslog +# Required-Stop: $local_fs $network $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop the FRR routing suite +# Description: FRR is a routing suite for IP routing protocols like +# BGP, OSPF, RIP and others. This script contols the main +# "watchfrr" daemon. +### END INIT INFO +# +# This is the main init script for FRR. It mostly wraps frrcommon.sh which +# provides the actual functions to start/stop/restart things. +# + +if [ -r "/lib/lsb/init-functions" ]; then + . /lib/lsb/init-functions +else + log_success_msg() { + echo "$@" + } + log_warning_msg() { + echo "$@" >&2 + } + log_failure_msg() { + echo "$@" >&2 + } +fi + +self="`dirname $0`" +if [ -r "$self/frrcommon.sh" ]; then + . "$self/frrcommon.sh" +else + . "@CFG_SBIN@/frrcommon.sh" +fi + +case "$1" in +start) + daemon_list daemons + watchfrr_options="$watchfrr_options $daemons" + daemon_start watchfrr + ;; +stop) + daemon_stop watchfrr + all_stop --reallyall + exit ${still_running:-0} + ;; + +restart|force-reload) + daemon_stop watchfrr + all_stop --reallyall + + daemon_list daemons + watchfrr_options="$watchfrr_options $daemons" + daemon_start watchfrr + ;; + +status) + fail=0 + print_status watchfrr || fail=1 + all_status || fail=1 + exit $fail + ;; + +reload) + if [ ! -x "$RELOAD_SCRIPT" ]; then + log_failure_msg "The frr-pythontools package is required for reload functionality." + exit 1 + fi + + # restart watchfrr to pick up added daemons. + # NB: This will NOT cause the other daemons to be restarted. + daemon_list daemons + watchfrr_options="$watchfrr_options $daemons" + daemon_stop watchfrr && \ + daemon_start watchfrr + + NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}" + [ ! -r $NEW_CONFIG_FILE ] && log_failure_msg "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1 + "$RELOAD_SCRIPT" --reload "$NEW_CONFIG_FILE" + exit $? + ;; + +*) + log_failure_msg "Unknown command: $1" >&2 + exit 1 +esac diff --git a/tools/subdir.am b/tools/subdir.am index 2e68dfee09..ff41fe2c63 100644 --- a/tools/subdir.am +++ b/tools/subdir.am @@ -13,6 +13,10 @@ sbin_SCRIPTS += \ tools/frr-reload \ tools/frr-reload.py \ tools/frr \ + \ + tools/frrcommon.sh \ + tools/frrinit.sh \ + tools/watchfrr.sh \ # end tools_permutations_SOURCES = tools/permutations.c diff --git a/tools/watchfrr.sh.in b/tools/watchfrr.sh.in new file mode 100644 index 0000000000..3051d91044 --- /dev/null +++ b/tools/watchfrr.sh.in @@ -0,0 +1,33 @@ +#!/bin/sh +# +# This is NOT the init script! This is the watchfrr start/stop/restart +# command handler, passed to watchfrr with the -s/-r/-k commands. It is used +# internally by watchfrr to start the protocol daemons with the appropriate +# options. +# +# This script should be installed in @CFG_SBIN@/watchfrr.sh + +log_success_msg() { + : +} + +log_warning_msg() { + echo "$@" >&2 + [ -x /usr/bin/logger ] && echo "$@" \ + | /usr/bin/logger -t watchfrr.sh -p daemon.warn +} + +log_failure_msg() { + echo "$@" >&2 + [ -x /usr/bin/logger ] && echo "$@" \ + | /usr/bin/logger -t watchfrr.sh -p daemon.err +} + +self="`dirname $0`" +if [ -r "$self/frrcommon.sh" ]; then + . "$self/frrcommon.sh" +else + . "@CFG_SBIN@/frrcommon.sh" +fi + +frrcommon_main "$@" From 9c830772cd5cf74c1c47fab8b492d89e2ddbcc96 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 6 Dec 2018 14:34:13 +0100 Subject: [PATCH 6/7] *: get rid of most daemons.conf references There's a few left over to get compatibility and not break user installs, but most is gone. Signed-off-by: David Lamparter --- alpine/APKBUILD.in | 3 +- debianpkg/README.Debian | 2 +- doc/developer/building-frr-for-alpine.rst | 1 - doc/developer/building-frr-for-ubuntu1204.rst | 1 - doc/developer/building-frr-for-ubuntu1404.rst | 1 - doc/developer/building-frr-for-ubuntu1604.rst | 2 -- doc/developer/building-frr-for-ubuntu1804.rst | 2 -- doc/user/rpki.rst | 8 ++--- doc/user/setup.rst | 2 +- tools/etc/default/frr | 10 ------ tools/etc/frr/daemons | 34 +++++++++++++++++++ tools/etc/frr/daemons.conf | 34 +------------------ 12 files changed, 42 insertions(+), 58 deletions(-) delete mode 100644 tools/etc/default/frr diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in index 42896c21a5..969b85f524 100644 --- a/alpine/APKBUILD.in +++ b/alpine/APKBUILD.in @@ -23,7 +23,7 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl checkdepends="pytest py-setuptools" install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall" subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg" -source="$pkgname-$pkgver.tar.gz docker-start daemons daemons.conf" +source="$pkgname-$pkgver.tar.gz docker-start daemons" builddir="$srcdir"/$pkgname-$pkgver @@ -62,7 +62,6 @@ package() { install -Dm755 "$srcdir"/docker-start "$pkgdir"$_sbindir install -Dm644 "$srcdir"/daemons "$pkgdir"$_sysconfdir - install -Dm644 "$srcdir"/daemons.conf "$pkgdir"$_sysconfdir install -d "$pkgdir"/etc/init.d ln -s ${_sbindir}/frr "$pkgdir"/etc/init.d/frr } diff --git a/debianpkg/README.Debian b/debianpkg/README.Debian index 1b04803366..cd7be5e801 100644 --- a/debianpkg/README.Debian +++ b/debianpkg/README.Debian @@ -83,7 +83,7 @@ into the kernel. ===================================================================== If this message occurs the receive buffer should be increased by adding the -following to /etc/sysctl.conf and "--nl-bufsize" to /etc/frr/daemons.conf. +following to /etc/sysctl.conf and "--nl-bufsize" to /etc/frr/daemons. > net.core.rmem_default = 262144 > net.core.rmem_max = 262144 See message #4525 from 2005-05-09 in the quagga-users mailing list. diff --git a/doc/developer/building-frr-for-alpine.rst b/doc/developer/building-frr-for-alpine.rst index d303784d4e..f88fc7bfdc 100644 --- a/doc/developer/building-frr-for-alpine.rst +++ b/doc/developer/building-frr-for-alpine.rst @@ -85,7 +85,6 @@ startup. To configure by hand: docker exec -it frr /bin/sh vi /etc/frr/daemons - vi /etc/frr/daemons.conf cp /etc/frr/zebra.conf.sample /etc/frr/zebra.conf vi /etc/frr/zebra.conf /etc/init.d/frr start diff --git a/doc/developer/building-frr-for-ubuntu1204.rst b/doc/developer/building-frr-for-ubuntu1204.rst index 9b2394f018..a2d58e2258 100644 --- a/doc/developer/building-frr-for-ubuntu1204.rst +++ b/doc/developer/building-frr-for-ubuntu1204.rst @@ -158,7 +158,6 @@ Install the init.d service sudo install -m 755 tools/frr /etc/init.d/frr sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons - sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf Enable daemons diff --git a/doc/developer/building-frr-for-ubuntu1404.rst b/doc/developer/building-frr-for-ubuntu1404.rst index 81ca970469..7952cd682a 100644 --- a/doc/developer/building-frr-for-ubuntu1404.rst +++ b/doc/developer/building-frr-for-ubuntu1404.rst @@ -112,7 +112,6 @@ Install the init.d service sudo install -m 755 tools/frr /etc/init.d/frr sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons - sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf Enable daemons diff --git a/doc/developer/building-frr-for-ubuntu1604.rst b/doc/developer/building-frr-for-ubuntu1604.rst index 9830b24dfc..f5329fef2c 100644 --- a/doc/developer/building-frr-for-ubuntu1604.rst +++ b/doc/developer/building-frr-for-ubuntu1604.rst @@ -139,9 +139,7 @@ Install the systemd service (if rebooted from last step, change directory back t :: sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service - sudo install -m 644 tools/etc/default/frr /etc/default/frr sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons - sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf diff --git a/doc/developer/building-frr-for-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst index e69ded8f73..110bc6a0ee 100644 --- a/doc/developer/building-frr-for-ubuntu1804.rst +++ b/doc/developer/building-frr-for-ubuntu1804.rst @@ -203,9 +203,7 @@ Install the systemd service :: sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service - sudo install -m 644 tools/etc/default/frr /etc/default/frr sudo install -m 644 tools/etc/frr/daemons /etc/frr/daemons - sudo install -m 644 tools/etc/frr/daemons.conf /etc/frr/daemons.conf sudo install -m 644 tools/etc/frr/frr.conf /etc/frr/frr.conf sudo install -m 644 -o frr -g frr tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst index f48ff2e6ba..295a26fda9 100644 --- a/doc/user/rpki.rst +++ b/doc/user/rpki.rst @@ -67,17 +67,17 @@ Enabling RPKI to configure at least one reachable cache server. See section :ref:`configuring-rpki-rtr-cache-servers` for configuring a cache server. -.. index:: RPKI and daemons.conf +.. index:: RPKI and daemons When first installing FRR with RPKI support from the pre-packaged binaries. Remember to add ``-M rpki`` to the variable ``bgpd_options`` in -:file:`/etc/frr/daemons.conf` , like so:: +:file:`/etc/frr/daemons` , like so:: - bgpd_options=" --daemon -A 127.0.0.1 -M rpki" + bgpd_options=" -A 127.0.0.1 -M rpki" instead of the default setting:: - bgpd_options=" --daemon -A 127.0.0.1" + bgpd_options=" -A 127.0.0.1" Otherwise you will encounter an error when trying to enter RPKI configuration mode due to the ``rpki`` module not being loaded when the BGP diff --git a/doc/user/setup.rst b/doc/user/setup.rst index 8a76a61e78..3a09c50309 100644 --- a/doc/user/setup.rst +++ b/doc/user/setup.rst @@ -41,7 +41,7 @@ Daemons Configuration File -------------------------- There is another file that controls the default options passed to daemons when starting FRR as a service. This file is located in your configuration -directory, usually at :file:`/etc/frr/daemons.conf`. +directory, usually at :file:`/etc/frr/daemons`. This file has several parts. Here is an example: diff --git a/tools/etc/default/frr b/tools/etc/default/frr deleted file mode 100644 index 693fa63390..0000000000 --- a/tools/etc/default/frr +++ /dev/null @@ -1,10 +0,0 @@ -MAX_INSTANCES=5 -MAX_FDS=1024 -ZEBRA_OPTIONS="-s 16777216 -A 127.0.0.1" -BGPD_OPTIONS="-A 127.0.0.1" -OSPFD_OPTIONS="-A 127.0.0.1" -OSPF6D_OPTIONS="-A ::1" -RIPD_OPTIONS="-A 127.0.0.1" -RIPNGD_OPTIONS="-A ::1" -ISISD_OPTIONS="-A 127.0.0.1" -EIGRP_OPTIONS="-A 127.0.0.1" diff --git a/tools/etc/frr/daemons b/tools/etc/frr/daemons index 3f513bf618..2d56fe1b98 100644 --- a/tools/etc/frr/daemons +++ b/tools/etc/frr/daemons @@ -29,3 +29,37 @@ sharpd=no pbrd=no bfdd=no fabricd=no + +# +# If this option is set the /etc/init.d/frr script automatically loads +# the config via "vtysh -b" when the servers are started. +# Check /etc/pam.d/frr if you intend to use "vtysh"! +# +vtysh_enable=yes +zebra_options=" -A 127.0.0.1 -s 90000000" +bgpd_options=" -A 127.0.0.1" +ospfd_options=" -A 127.0.0.1" +ospf6d_options=" -A ::1" +ripd_options=" -A 127.0.0.1" +ripngd_options=" -A ::1" +isisd_options=" -A 127.0.0.1" +pimd_options=" -A 127.0.0.1" +ldpd_options=" -A 127.0.0.1" +nhrpd_options=" -A 127.0.0.1" +eigrpd_options=" -A 127.0.0.1" +babeld_options=" -A 127.0.0.1" +sharpd_options=" -A 127.0.0.1" +pbrd_options=" -A 127.0.0.1" +staticd_options="-A 127.0.0.1" +bfdd_options=" -A 127.0.0.1" +fabricd_options="-A 127.0.0.1" + +# The list of daemons to watch is automatically generated by the init script. +watchfrr_options="-r '/usr/lib/frr/watchfrr.sh restart %s' -s '/usr/lib/frr/watchfrr.sh start %s' -k '/usr/lib/frr/watchfrr.sh stop %s'" + +# for debugging purposes, you can specify a "wrap" command to start instead +# of starting the daemon directly, e.g. to use valgrind on ospfd: +# ospfd_wrap="/usr/bin/valgrind" +# or you can use "all_wrap" for all daemons, e.g. to use perf record: +# all_wrap="/usr/bin/perf record --call-graph -" +# the normal daemon command is added to this at the end. diff --git a/tools/etc/frr/daemons.conf b/tools/etc/frr/daemons.conf index 02a785c87a..70b96a9800 100644 --- a/tools/etc/frr/daemons.conf +++ b/tools/etc/frr/daemons.conf @@ -1,33 +1 @@ -# -# If this option is set the /etc/init.d/frr script automatically loads -# the config via "vtysh -b" when the servers are started. -# Check /etc/pam.d/frr if you intend to use "vtysh"! -# -vtysh_enable=yes -zebra_options=" -A 127.0.0.1 -s 90000000" -bgpd_options=" -A 127.0.0.1" -ospfd_options=" -A 127.0.0.1" -ospf6d_options=" -A ::1" -ripd_options=" -A 127.0.0.1" -ripngd_options=" -A ::1" -isisd_options=" -A 127.0.0.1" -pimd_options=" -A 127.0.0.1" -ldpd_options=" -A 127.0.0.1" -nhrpd_options=" -A 127.0.0.1" -eigrpd_options=" -A 127.0.0.1" -babeld_options=" -A 127.0.0.1" -sharpd_options=" -A 127.0.0.1" -pbrd_options=" -A 127.0.0.1" -staticd_options="-A 127.0.0.1" -bfdd_options=" -A 127.0.0.1" -fabricd_options="-A 127.0.0.1" - -# The list of daemons to watch is automatically generated by the init script. -watchfrr_options="-r '/usr/lib/frr/watchfrr.sh restart %s' -s '/usr/lib/frr/watchfrr.sh start %s' -k '/usr/lib/frr/watchfrr.sh stop %s'" - -# for debugging purposes, you can specify a "wrap" command to start instead -# of starting the daemon directly, e.g. to use valgrind on ospfd: -# ospfd_wrap="/usr/bin/valgrind" -# or you can use "all_wrap" for all daemons, e.g. to use perf record: -# all_wrap="/usr/bin/perf record --call-graph -" -# the normal daemon command is added to this at the end. +# this file is deprecated, please use "daemons" instead. From 76fd52625de1e00c1cc9d4f49f24b4caaaeeded1 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 8 Nov 2018 06:50:13 +0100 Subject: [PATCH 7/7] vtysh: rework/straighten pager handling - no longer try to special-case a custom terminal length; the OS has procedures for that (SIGWINCH & TIOCGWINSZ) - only use a pager if requested by CLI command or VTYSH_PAGER. The behaviour with VTYSH_PAGER set should be compatible to previous versions. Signed-off-by: David Lamparter --- vtysh/vtysh.c | 61 ++++++++++++++++++++++++++-------------------- vtysh/vtysh.h | 2 -- vtysh/vtysh_main.c | 2 -- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index f57a4d9ddf..2327f2b46d 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -104,7 +104,7 @@ static int vty_close_pager(struct vty *vty) return 0; } -void vtysh_pager_init(void) +static void vtysh_pager_envdef(void) { char *pager_defined; @@ -2881,52 +2881,58 @@ DEFUN (vtysh_copy_running_config, return vtysh_write_memory(self, vty, argc, argv); } +DEFUN (vtysh_terminal_paginate, + vtysh_terminal_paginate_cmd, + "[no] terminal paginate", + NO_STR + "Set terminal line parameters\n" + "Use pager for output scrolling\n") +{ + free(vtysh_pager_name); + vtysh_pager_name = NULL; + + if (strcmp(argv[0]->text, "no")) + vtysh_pager_envdef(); + return CMD_SUCCESS; +} + DEFUN (vtysh_terminal_length, vtysh_terminal_length_cmd, - "terminal length (0-512)", + "[no] terminal length (0-4294967295)", + NO_STR "Set terminal line parameters\n" "Set number of lines on a screen\n" - "Number of lines on screen (0 for no pausing)\n") + "Number of lines on screen (0 for no pausing, nonzero to use pager)\n") { int idx_number = 2; - int lines; - char *endptr = NULL; - char default_pager[10]; + unsigned long lines; - lines = strtol(argv[idx_number]->arg, &endptr, 10); - if (lines < 0 || lines > 512 || *endptr != '\0') { - vty_out(vty, "length is malformed\n"); - return CMD_WARNING; - } - - if (vtysh_pager_name) { - free(vtysh_pager_name); - vtysh_pager_name = NULL; + free(vtysh_pager_name); + vtysh_pager_name = NULL; + + if (!strcmp(argv[0]->text, "no") || !strcmp(argv[1]->text, "no")) { + /* "terminal no length" = use VTYSH_PAGER */ + vtysh_pager_envdef(); + return CMD_SUCCESS; } + lines = strtoul(argv[idx_number]->arg, NULL, 10); if (lines != 0) { - snprintf(default_pager, 10, "more -%i", lines); - vtysh_pager_name = strdup(default_pager); + vty_out(vty, + "%% The \"terminal length\" command is deprecated and its value is ignored.\n" + "%% Please use \"terminal paginate\" instead with OS TTY length handling.\n"); + vtysh_pager_envdef(); } return CMD_SUCCESS; } -DEFUN (vtysh_terminal_no_length, +ALIAS_DEPRECATED(vtysh_terminal_length, vtysh_terminal_no_length_cmd, "terminal no length", "Set terminal line parameters\n" NO_STR "Set number of lines on a screen\n") -{ - if (vtysh_pager_name) { - free(vtysh_pager_name); - vtysh_pager_name = NULL; - } - - vtysh_pager_init(); - return CMD_SUCCESS; -} DEFUN (vtysh_show_daemons, vtysh_show_daemons_cmd, @@ -3805,6 +3811,7 @@ void vtysh_init_vty(void) /* "write memory" command. */ install_element(ENABLE_NODE, &vtysh_write_memory_cmd); + install_element(VIEW_NODE, &vtysh_terminal_paginate_cmd); install_element(VIEW_NODE, &vtysh_terminal_length_cmd); install_element(VIEW_NODE, &vtysh_terminal_no_length_cmd); install_element(VIEW_NODE, &vtysh_show_daemons_cmd); diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 430b117c50..eb69a20b83 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -98,8 +98,6 @@ void vtysh_config_dump(void); void vtysh_config_init(void); -void vtysh_pager_init(void); - void suid_on(void); void suid_off(void); diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 777eed7b5d..2e4510a45a 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -675,8 +675,6 @@ int main(int argc, char **argv, char **env) exit(0); } - vtysh_pager_init(); - vtysh_readline_init(); vty_hello(vty);