]> git.proxmox.com Git - mirror_frr.git/blobdiff - vtysh/vtysh.c
lib: enforce vrf_name_to_id by returning default_vrf when name is null
[mirror_frr.git] / vtysh / vtysh.c
index 290d8f50e5e3c0d146b8d68501969626400d9ef2..2327f2b46d7e04219518ab89d5d7fe849d307db9 100644 (file)
 #include "vrf.h"
 #include "libfrr.h"
 #include "command_graph.h"
+#include "frrstr.h"
+#include "json.h"
 
 DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy")
 
-/* Destination for vtysh output */
-FILE *outputfile;
-
 /* Struct VTY. */
 struct vty *vty;
 
 /* VTY shell pager name. */
 char *vtysh_pager_name = NULL;
 
-/* VTY shell client structure. */
+/* VTY shell client structure */
 struct vtysh_client {
        int fd;
        const char *name;
@@ -65,6 +64,60 @@ struct vtysh_client {
        struct vtysh_client *next;
 };
 
+/* Some utility functions for working on vtysh-specific vty tasks */
+
+static FILE *vty_open_pager(struct vty *vty)
+{
+       if (vty->is_paged)
+               return vty->of;
+
+       if (!vtysh_pager_name)
+               return NULL;
+
+       vty->of_saved = vty->of;
+       vty->of = popen(vtysh_pager_name, "w");
+       if (vty->of == NULL) {
+               vty->of = vty->of_saved;
+               perror("popen");
+               exit(1);
+       }
+
+       vty->is_paged = true;
+
+       return vty->of;
+}
+
+static int vty_close_pager(struct vty *vty)
+{
+       if (!vty->is_paged)
+               return 0;
+
+       fflush(vty->of);
+       if (pclose(vty->of) == -1) {
+               perror("pclose");
+               exit(1);
+       }
+
+       vty->of = vty->of_saved;
+       vty->is_paged = false;
+
+       return 0;
+}
+
+static void vtysh_pager_envdef(void)
+{
+       char *pager_defined;
+
+       pager_defined = getenv("VTYSH_PAGER");
+
+       if (pager_defined)
+               vtysh_pager_name = strdup(pager_defined);
+       else
+               vtysh_pager_name = strdup(VTYSH_PAGER);
+}
+
+/* --- */
+
 struct vtysh_client vtysh_client[] = {
        {.fd = -1, .name = "zebra", .flag = VTYSH_ZEBRA, .next = NULL},
        {.fd = -1, .name = "ripd", .flag = VTYSH_RIPD, .next = NULL},
@@ -79,8 +132,11 @@ struct vtysh_client vtysh_client[] = {
        {.fd = -1, .name = "eigrpd", .flag = VTYSH_EIGRPD, .next = NULL},
        {.fd = -1, .name = "babeld", .flag = VTYSH_BABELD, .next = NULL},
        {.fd = -1, .name = "sharpd", .flag = VTYSH_SHARPD, .next = NULL},
+       {.fd = -1, .name = "fabricd", .flag = VTYSH_FABRICD, .next = NULL},
        {.fd = -1, .name = "watchfrr", .flag = VTYSH_WATCHFRR, .next = NULL},
        {.fd = -1, .name = "pbrd", .flag = VTYSH_PBRD, .next = NULL},
+       {.fd = -1, .name = "staticd", .flag = VTYSH_STATICD, .next = NULL},
+       {.fd = -1, .name = "bfdd", .flag = VTYSH_BFDD, .next = NULL},
 };
 
 enum vtysh_write_integrated vtysh_write_integrated =
@@ -91,7 +147,7 @@ static int vtysh_reconnect(struct vtysh_client *vclient);
 static void vclient_close(struct vtysh_client *vclient)
 {
        if (vclient->fd >= 0) {
-               fprintf(stderr,
+               vty_out(vty,
                        "Warning: closing connection to %s because of an I/O error!\n",
                        vclient->name);
                close(vclient->fd);
@@ -100,21 +156,30 @@ static void vclient_close(struct vtysh_client *vclient)
        }
 }
 
-/* Return true if str begins with prefix, else return false */
-static int begins_with(const char *str, const char *prefix)
-{
-       if (!str || !prefix)
-               return 0;
-       size_t lenstr = strlen(str);
-       size_t lenprefix = strlen(prefix);
-       if (lenprefix > lenstr)
-               return 0;
-       return strncmp(str, prefix, lenprefix) == 0;
-}
-
+/*
+ * Send a CLI command to a client and read the response.
+ *
+ * Output will be printed to vty->of. If you want to suppress output, set that
+ * to NULL.
+ *
+ * vclient
+ *    the client to send the command to
+ *
+ * line
+ *    the command to send
+ *
+ * callback
+ *    if non-null, this will be called with each line of output received from
+ *    the client passed in the second parameter
+ *
+ * cbarg
+ *    optional first argument to pass to callback
+ *
+ * Returns:
+ *    a status code
+ */
 static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
-                           FILE *fp, void (*callback)(void *, const char *),
-                           void *cbarg)
+                           void (*callback)(void *, const char *), void *cbarg)
 {
        int ret;
        char stackbuf[4096];
@@ -155,7 +220,7 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
                        continue;
 
                if (nread <= 0) {
-                       fprintf(stderr, "vtysh: error reading from %s: %s (%d)",
+                       vty_out(vty, "vtysh: error reading from %s: %s (%d)",
                                vclient->name, safe_strerror(errno), errno);
                        goto out_err;
                }
@@ -227,12 +292,10 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
                        /* eol is at line end now, either \n => \0 or \0\0\0 */
                        assert(eol && eol <= bufvalid);
 
-                       if (fp) {
-                               fputs(buf, fp);
-                               fputc('\n', fp);
-                       }
-                       if (callback)
-                               callback(cbarg, buf);
+                       if (vty->of)
+                               vty_out(vty, "%s\n", buf);
+
+                       callback(cbarg, buf);
 
                        /* shift back data and adjust bufvalid */
                        memmove(buf, eol, bufvalid - eol);
@@ -243,8 +306,8 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
 
                /* else if no callback, dump raw */
                if (!callback) {
-                       if (fp)
-                               fwrite(buf, 1, textlen, fp);
+                       if (vty->of)
+                               vty_out(vty, "%s", buf);
                        memmove(buf, buf + textlen, bufvalid - buf - textlen);
                        bufvalid -= textlen;
                        if (end)
@@ -281,7 +344,7 @@ out:
 }
 
 static int vtysh_client_run_all(struct vtysh_client *head_client,
-                               const char *line, int continue_on_err, FILE *fp,
+                               const char *line, int continue_on_err,
                                void (*callback)(void *, const char *),
                                void *cbarg)
 {
@@ -290,7 +353,7 @@ static int vtysh_client_run_all(struct vtysh_client *head_client,
        int correct_instance = 0, wrong_instance = 0;
 
        for (client = head_client; client; client = client->next) {
-               rc = vtysh_client_run(client, line, fp, callback, cbarg);
+               rc = vtysh_client_run(client, line, callback, cbarg);
                if (rc == CMD_NOT_MY_INSTANCE) {
                        wrong_instance++;
                        continue;
@@ -303,8 +366,8 @@ static int vtysh_client_run_all(struct vtysh_client *head_client,
                        rc_all = rc;
                }
        }
-       if (wrong_instance && !correct_instance && fp) {
-               fprintf(fp,
+       if (wrong_instance && !correct_instance) {
+               vty_out(vty,
                        "%% [%s]: command ignored as it targets an instance that is not running\n",
                        head_client->name);
                rc_all = CMD_WARNING_CONFIG_FAILED;
@@ -312,12 +375,34 @@ static int vtysh_client_run_all(struct vtysh_client *head_client,
        return rc_all;
 }
 
+/*
+ * Execute command against all daemons.
+ *
+ * head_client
+ *    where to start walking in the daemon list
+ *
+ * line
+ *    the specific command to execute
+ *
+ * Returns:
+ *    a status code
+ */
 static int vtysh_client_execute(struct vtysh_client *head_client,
-                               const char *line, FILE *fp)
+                               const char *line)
 {
-       return vtysh_client_run_all(head_client, line, 0, fp, NULL, NULL);
+       return vtysh_client_run_all(head_client, line, 0, NULL, NULL);
 }
 
+/*
+ * Retrieve all running config from daemons and parse it with the vtysh config
+ * parser. Returned output is not displayed to the user.
+ *
+ * head_client
+ *    where to start walking in the daemon list
+ *
+ * line
+ *    the specific command to execute
+ */
 static void vtysh_client_config(struct vtysh_client *head_client, char *line)
 {
        /* watchfrr currently doesn't load any config, and has some hardcoded
@@ -327,20 +412,12 @@ static void vtysh_client_config(struct vtysh_client *head_client, char *line)
        if (head_client->flag == VTYSH_WATCHFRR)
                return;
 
-       vtysh_client_run_all(head_client, line, 1, NULL,
-                            vtysh_config_parse_line, NULL);
-}
-
-void vtysh_pager_init(void)
-{
-       char *pager_defined;
-
-       pager_defined = getenv("VTYSH_PAGER");
-
-       if (pager_defined)
-               vtysh_pager_name = strdup(pager_defined);
-       else
-               vtysh_pager_name = strdup(VTYSH_PAGER);
+       /* suppress output to user */
+       vty->of_saved = vty->of;
+       vty->of = NULL;
+       vtysh_client_run_all(head_client, line, 1, vtysh_config_parse_line,
+                            NULL);
+       vty->of = vty->of_saved;
 }
 
 /* Command execution over the vty interface. */
@@ -350,8 +427,6 @@ static int vtysh_execute_func(const char *line, int pager)
        unsigned int i;
        vector vline;
        const struct cmd_element *cmd;
-       FILE *fp = NULL;
-       int closepager = 0;
        int tried = 0;
        int saved_ret, saved_node;
 
@@ -364,12 +439,12 @@ static int vtysh_execute_func(const char *line, int pager)
        if (user_mode) {
                if (strncmp("en", vector_slot(vline, 0), 2) == 0) {
                        cmd_free_strvec(vline);
-                       fprintf(stdout, "%% Command not allowed: enable\n");
+                       vty_out(vty, "%% Command not allowed: enable\n");
                        return CMD_WARNING;
                }
        }
 
-       saved_ret = ret = cmd_execute_command(vline, vty, &cmd, 1);
+       saved_ret = ret = cmd_execute(vty, line, &cmd, 1);
        saved_node = vty->node;
 
        /*
@@ -381,7 +456,7 @@ static int vtysh_execute_func(const char *line, int pager)
               && ret != CMD_WARNING && ret != CMD_WARNING_CONFIG_FAILED
               && vty->node > CONFIG_NODE) {
                vty->node = node_parent(vty->node);
-               ret = cmd_execute_command(vline, vty, &cmd, 1);
+               ret = cmd_execute(vty, line, &cmd, 1);
                tried++;
        }
 
@@ -445,16 +520,16 @@ static int vtysh_execute_func(const char *line, int pager)
        case CMD_WARNING:
        case CMD_WARNING_CONFIG_FAILED:
                if (vty->type == VTY_FILE)
-                       fprintf(stdout, "Warning...\n");
+                       vty_out(vty, "Warning...\n");
                break;
        case CMD_ERR_AMBIGUOUS:
-               fprintf(stdout, "%% Ambiguous command: %s\n", line);
+               vty_out(vty, "%% Ambiguous command: %s\n", line);
                break;
        case CMD_ERR_NO_MATCH:
-               fprintf(stdout, "%% Unknown command: %s\n", line);
+               vty_out(vty, "%% Unknown command: %s\n", line);
                break;
        case CMD_ERR_INCOMPLETE:
-               fprintf(stdout, "%% Command incomplete: %s\n", line);
+               vty_out(vty, "%% Command incomplete: %s\n", line);
                break;
        case CMD_SUCCESS_DAEMON: {
                /*
@@ -462,21 +537,13 @@ static int vtysh_execute_func(const char *line, int pager)
                 * problems if exited from vtysh at all. This hack shouldn't
                 * cause any problem but is really ugly.
                 */
-               fp = outputfile;
-               if (pager && vtysh_pager_name && outputfile == stdout
-                   && (strncmp(line, "exit", 4) != 0)) {
-                       fp = popen(vtysh_pager_name, "w");
-                       if (fp == NULL) {
-                               perror("popen failed for pager");
-                               fp = outputfile;
-                       } else
-                               closepager = 1;
-               }
+               if (pager && strncmp(line, "exit", 4))
+                       vty_open_pager(vty);
 
                if (!strcmp(cmd->string, "configure terminal")) {
                        for (i = 0; i < array_size(vtysh_client); i++) {
                                cmd_stat = vtysh_client_execute(
-                                       &vtysh_client[i], line, fp);
+                                       &vtysh_client[i], line);
                                if (cmd_stat == CMD_WARNING)
                                        break;
                        }
@@ -485,14 +552,10 @@ static int vtysh_execute_func(const char *line, int pager)
                                line = "end";
                                vline = cmd_make_strvec(line);
 
+
                                if (vline == NULL) {
-                                       if (pager && vtysh_pager_name && fp
-                                           && fp != outputfile && closepager) {
-                                               if (pclose(fp) == -1) {
-                                                       perror("pclose failed for pager");
-                                               }
-                                               fp = NULL;
-                                       }
+                                       if (vty->is_paged)
+                                               vty_close_pager(vty);
                                        return CMD_SUCCESS;
                                }
 
@@ -514,7 +577,7 @@ static int vtysh_execute_func(const char *line, int pager)
                                    && (cmd->daemon == vtysh_client[i].flag)) {
                                        for (vc = &vtysh_client[i]; vc;
                                             vc = vc->next)
-                                               if (vc->fd < 0)
+                                               if (vc->fd == VTYSH_WAS_ACTIVE)
                                                        vtysh_reconnect(vc);
                                }
                                if (vtysh_client[i].fd < 0
@@ -532,7 +595,7 @@ static int vtysh_execute_func(const char *line, int pager)
                                        }
                                }
                                cmd_stat = vtysh_client_execute(
-                                       &vtysh_client[i], line, fp);
+                                       &vtysh_client[i], line);
                                if (cmd_stat != CMD_SUCCESS)
                                        break;
                        }
@@ -544,12 +607,9 @@ static int vtysh_execute_func(const char *line, int pager)
                        (*cmd->func)(cmd, vty, 0, NULL);
        }
        }
-       if (pager && vtysh_pager_name && fp && closepager && fp != outputfile) {
-               if (pclose(fp) == -1) {
-                       perror("pclose failed for pager");
-               }
-               fp = NULL;
-       }
+       if (vty->is_paged)
+               vty_close_pager(vty);
+
        return cmd_stat;
 }
 
@@ -626,19 +686,19 @@ int vtysh_mark_file(const char *filename)
                switch (vty->node) {
                case LDP_IPV4_IFACE_NODE:
                        if (strncmp(vty_buf_copy, "   ", 3)) {
-                               fprintf(outputfile, "  end\n");
+                               vty_out(vty, "  end\n");
                                vty->node = LDP_IPV4_NODE;
                        }
                        break;
                case LDP_IPV6_IFACE_NODE:
                        if (strncmp(vty_buf_copy, "   ", 3)) {
-                               fprintf(outputfile, "  end\n");
+                               vty_out(vty, "  end\n");
                                vty->node = LDP_IPV6_NODE;
                        }
                        break;
                case LDP_PSEUDOWIRE_NODE:
                        if (strncmp(vty_buf_copy, "  ", 2)) {
-                               fprintf(outputfile, " end\n");
+                               vty_out(vty, " end\n");
                                vty->node = LDP_L2VPN_NODE;
                        }
                        break;
@@ -647,7 +707,7 @@ int vtysh_mark_file(const char *filename)
                }
 
                if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') {
-                       fprintf(outputfile, "%s", vty->buf);
+                       vty_out(vty, "%s", vty->buf);
                        continue;
                }
 
@@ -655,7 +715,7 @@ int vtysh_mark_file(const char *filename)
                vline = cmd_make_strvec(vty->buf);
 
                if (vline == NULL) {
-                       fprintf(outputfile, "%s", vty->buf);
+                       vty_out(vty, "%s", vty->buf);
                        continue;
                }
 
@@ -704,15 +764,15 @@ int vtysh_mark_file(const char *filename)
                             || prev_node == BGP_IPV6M_NODE
                             || prev_node == BGP_EVPN_NODE)
                            && (tried == 1)) {
-                               fprintf(outputfile, "exit-address-family\n");
+                               vty_out(vty, "exit-address-family\n");
                        } else if ((prev_node == BGP_EVPN_VNI_NODE)
                                   && (tried == 1)) {
-                               fprintf(outputfile, "exit-vni\n");
+                               vty_out(vty, "exit-vni\n");
                        } else if ((prev_node == KEYCHAIN_KEY_NODE)
                                   && (tried == 1)) {
-                               fprintf(outputfile, "exit\n");
+                               vty_out(vty, "exit\n");
                        } else if (tried) {
-                               fprintf(outputfile, "end\n");
+                               vty_out(vty, "end\n");
                        }
                }
                /*
@@ -757,22 +817,14 @@ int vtysh_mark_file(const char *filename)
                        XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
                        return CMD_ERR_INCOMPLETE;
                case CMD_SUCCESS:
-                       fprintf(stdout, "%s", vty->buf);
+                       vty_out(vty, "%s", vty->buf);
                        break;
                case CMD_SUCCESS_DAEMON: {
-                       unsigned int i;
-                       int cmd_stat = CMD_SUCCESS;
+                       int cmd_stat;
 
-                       fprintf(outputfile, "%s", vty->buf);
-                       for (i = 0; i < array_size(vtysh_client); i++) {
-                               if (cmd->daemon & vtysh_client[i].flag) {
-                                       cmd_stat = vtysh_client_execute(
-                                               &vtysh_client[i], vty->buf,
-                                               outputfile);
-                                       if (cmd_stat != CMD_SUCCESS)
-                                               break;
-                               }
-                       }
+                       vty_out(vty, "%s", vty->buf);
+                       cmd_stat = vtysh_client_execute(&vtysh_client[0],
+                                                       vty->buf);
                        if (cmd_stat != CMD_SUCCESS)
                                break;
 
@@ -782,7 +834,7 @@ int vtysh_mark_file(const char *filename)
                }
        }
        /* This is the end */
-       fprintf(outputfile, "\nend\n");
+       vty_out(vty, "\nend\n");
        vty_close(vty);
        XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
 
@@ -804,7 +856,7 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp)
        while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
                lineno++;
 
-               ret = command_config_read_one_line(vty, &cmd, 1);
+               ret = command_config_read_one_line(vty, &cmd, lineno, 1);
 
                switch (ret) {
                case CMD_WARNING:
@@ -839,8 +891,7 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp)
                        for (i = 0; i < array_size(vtysh_client); i++) {
                                if (cmd->daemon & vtysh_client[i].flag) {
                                        cmd_stat = vtysh_client_execute(
-                                               &vtysh_client[i], vty->buf,
-                                               outputfile);
+                                               &vtysh_client[i], vty->buf);
                                        /*
                                         * CMD_WARNING - Can mean that the
                                         * command was parsed successfully but
@@ -904,14 +955,16 @@ static int vtysh_process_questionmark(const char *input, int input_len)
        case CMD_ERR_AMBIGUOUS:
                cmd_free_strvec(vline);
                vector_free(describe);
-               fprintf(stdout, "%% Ambiguous command.\n");
+               vty_out(vty, "%% Ambiguous command.\n");
+               rl_on_new_line();
                return 0;
                break;
        case CMD_ERR_NO_MATCH:
                cmd_free_strvec(vline);
                if (describe)
                        vector_free(describe);
-               fprintf(stdout, "%% There is no matched command.\n");
+               vty_out(vty, "%% There is no matched command.\n");
+               rl_on_new_line();
                return 0;
                break;
        }
@@ -932,10 +985,10 @@ static int vtysh_process_questionmark(const char *input, int input_len)
        for (i = 0; i < vector_active(describe); i++)
                if ((token = vector_slot(describe, i)) != NULL) {
                        if (!token->desc)
-                               fprintf(stdout, "  %-s\n", token->text);
+                               vty_out(vty, "  %-s\n", token->text);
                        else
-                               fprintf(stdout, "  %-*s  %s\n", width,
-                                       token->text, token->desc);
+                               vty_out(vty, "  %-*s  %s\n", width, token->text,
+                                       token->desc);
 
                        if (IS_VARYING_TOKEN(token->type)) {
                                const char *ref = vector_slot(
@@ -950,7 +1003,7 @@ static int vtysh_process_questionmark(const char *input, int input_len)
 
                                        char *ac = cmd_variable_comp2str(
                                                varcomps, cols);
-                                       fprintf(stdout, "%s\n", ac);
+                                       vty_out(vty, "%s\n", ac);
                                        XFREE(MTYPE_TMP, ac);
                                }
 
@@ -969,11 +1022,11 @@ static int vtysh_process_questionmark(const char *input, int input_len)
  * the usual vtysh's stdin interface. This is the function being registered with
  * readline() api's.
  */
-static int vtysh_rl_describe(void)
+static int vtysh_rl_describe(int a, int b)
 {
        int ret;
 
-       fprintf(stdout, "\n");
+       vty_out(vty, "\n");
 
        ret = vtysh_process_questionmark(rl_line_buffer, rl_end);
        rl_on_new_line();
@@ -1060,7 +1113,7 @@ static char *command_generator(const char *text, int state)
        return NULL;
 }
 
-static char **new_completion(char *text, int start, int end)
+static char **new_completion(const char *text, int start, int end)
 {
        char **matches;
 
@@ -1089,6 +1142,10 @@ static struct cmd_node isis_node = {
        ISIS_NODE, "%s(config-router)# ",
 };
 
+static struct cmd_node openfabric_node = {
+       OPENFABRIC_NODE, "%s(config-router)# ",
+};
+
 static struct cmd_node interface_node = {
        INTERFACE_NODE, "%s(config-if)# ",
 };
@@ -1200,9 +1257,19 @@ struct cmd_node link_params_node = {
        LINK_PARAMS_NODE, "%s(config-link-params)# ",
 };
 
-#if defined(HAVE_RPKI)
 static struct cmd_node rpki_node = {RPKI_NODE, "%s(config-rpki)# ", 1};
-#endif
+
+#if HAVE_BFDD > 0
+static struct cmd_node bfd_node = {
+       BFD_NODE,
+       "%s(config-bfd)# ",
+};
+
+static struct cmd_node bfd_peer_node = {
+       BFD_PEER_NODE,
+       "%s(config-bfd-peer)# ",
+};
+#endif /* HAVE_BFDD */
 
 /* Defined in lib/vty.c */
 extern struct cmd_node vty_node;
@@ -1360,7 +1427,6 @@ DEFUNSH(VTYSH_BGPD, address_family_ipv6_labeled_unicast,
        return CMD_SUCCESS;
 }
 
-#if defined(HAVE_RPKI)
 DEFUNSH(VTYSH_BGPD,
        rpki,
        rpki_cmd,
@@ -1371,26 +1437,6 @@ DEFUNSH(VTYSH_BGPD,
        return CMD_SUCCESS;
 }
 
-DEFUNSH(VTYSH_BGPD,
-       rpki_exit,
-       rpki_exit_cmd,
-       "exit",
-       "Exit current mode and down to previous mode\n")
-{
-       vty->node = CONFIG_NODE;
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_BGPD,
-       rpki_quit,
-       rpki_quit_cmd,
-       "quit",
-       "Exit current mode and down to previous mode\n")
-{
-       return rpki_exit(self, vty, argc, argv);
-}
-#endif
-
 DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
        "address-family <l2vpn evpn>",
        "Enter Address Family command mode\n"
@@ -1412,7 +1458,7 @@ DEFUNSH_HIDDEN(VTYSH_BGPD, address_family_evpn2, address_family_evpn2_cmd,
 }
 #endif
 
-DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni (1-16777215)",
+DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni " CMD_VNI_RANGE,
        "VXLAN Network Identifier\n"
        "VNI number\n")
 {
@@ -1456,7 +1502,7 @@ DEFUNSH(VTYSH_BGPD, vnc_l2_group, vnc_l2_group_cmd, "vnc l2-group NAME",
 }
 #endif
 
-DEFUNSH(VTYSH_RIPD, key_chain, key_chain_cmd, "key chain WORD",
+DEFUNSH(VTYSH_KEYS, key_chain, key_chain_cmd, "key chain WORD",
        "Authentication key management\n"
        "Key-chain management\n"
        "Key-chain name\n")
@@ -1465,7 +1511,7 @@ DEFUNSH(VTYSH_RIPD, key_chain, key_chain_cmd, "key chain WORD",
        return CMD_SUCCESS;
 }
 
-DEFUNSH(VTYSH_RIPD, key, key_cmd, "key (0-2147483647)",
+DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)",
        "Configure a key\n"
        "Key identifier number\n")
 {
@@ -1607,6 +1653,15 @@ DEFUNSH(VTYSH_ISISD, router_isis, router_isis_cmd, "router isis WORD",
        return CMD_SUCCESS;
 }
 
+DEFUNSH(VTYSH_FABRICD, router_openfabric, router_openfabric_cmd, "router openfabric WORD",
+       ROUTER_STR
+       "OpenFabric routing protocol\n"
+       "ISO Routing area tag\n")
+{
+       vty->node = OPENFABRIC_NODE;
+       return CMD_SUCCESS;
+}
+
 DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd,
        "route-map WORD <deny|permit> (1-65535)",
        "Create route-map or enter route-map command mode\n"
@@ -1630,6 +1685,32 @@ DEFUNSH(VTYSH_PBRD, vtysh_pbr_map, vtysh_pbr_map_cmd,
        return CMD_SUCCESS;
 }
 
+#if HAVE_BFDD > 0
+DEFUNSH(VTYSH_BFDD, bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n")
+{
+       vty->node = BFD_NODE;
+       return CMD_SUCCESS;
+}
+
+DEFUNSH(VTYSH_BFDD, bfd_peer_enter, bfd_peer_enter_cmd,
+       "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
+       "Configure peer\n"
+       "IPv4 peer address\n"
+       "IPv6 peer address\n"
+       "Configure multihop\n"
+       "Configure local address\n"
+       "IPv4 local address\n"
+       "IPv6 local address\n"
+       INTERFACE_STR
+       "Configure interface name to use\n"
+       "Configure VRF\n"
+       "Configure VRF name\n")
+{
+       vty->node = BFD_PEER_NODE;
+       return CMD_SUCCESS;
+}
+#endif /* HAVE_BFDD */
+
 DEFSH(VTYSH_PBRD, vtysh_no_pbr_map_cmd, "no pbr-map WORD [seq (1-700)]",
        NO_STR
        "Delete pbr-map\n"
@@ -1695,10 +1776,13 @@ static int vtysh_exit(struct vty *vty)
        case LDP_NODE:
        case LDP_L2VPN_NODE:
        case ISIS_NODE:
+       case OPENFABRIC_NODE:
        case RMAP_NODE:
        case PBRMAP_NODE:
        case VTY_NODE:
        case KEYCHAIN_NODE:
+       case BFD_NODE:
+       case RPKI_NODE:
                vtysh_execute("end");
                vtysh_execute("configure terminal");
                vty->node = CONFIG_NODE;
@@ -1742,6 +1826,9 @@ static int vtysh_exit(struct vty *vty)
        case LINK_PARAMS_NODE:
                vty->node = INTERFACE_NODE;
                break;
+       case BFD_PEER_NODE:
+               vty->node = BFD_NODE;
+               break;
        default:
                break;
        }
@@ -1789,6 +1876,20 @@ DEFUNSH(VTYSH_BGPD, exit_vnc_config, exit_vnc_config_cmd, "exit-vnc",
            || vty->node == BGP_VNC_L2_GROUP_NODE)
                vty->node = BGP_NODE;
        return CMD_SUCCESS;
+
+}
+
+DEFUNSH(VTYSH_BGPD, rpki_exit, rpki_exit_cmd, "exit",
+       "Exit current mode and down to previous mode\n")
+{
+       vtysh_exit(vty);
+       return CMD_SUCCESS;
+}
+
+DEFUNSH(VTYSH_BGPD, rpki_quit, rpki_quit_cmd, "quit",
+       "Exit current mode and down to previous mode\n")
+{
+       return rpki_exit(self, vty, argc, argv);
 }
 
 DEFUNSH(VTYSH_PIMD|VTYSH_ZEBRA, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf",
@@ -1938,6 +2039,29 @@ DEFUNSH(VTYSH_ISISD, vtysh_quit_isisd, vtysh_quit_isisd_cmd, "quit",
        return vtysh_exit_isisd(self, vty, argc, argv);
 }
 
+#if HAVE_BFDD > 0
+DEFUNSH(VTYSH_BFDD, vtysh_exit_bfdd, vtysh_exit_bfdd_cmd, "exit",
+       "Exit current mode and down to previous mode\n")
+{
+       return vtysh_exit(vty);
+}
+
+ALIAS(vtysh_exit_bfdd, vtysh_quit_bfdd_cmd, "quit",
+      "Exit current mode and down to previous mode\n")
+#endif
+
+DEFUNSH(VTYSH_FABRICD, vtysh_exit_fabricd, vtysh_exit_fabricd_cmd, "exit",
+       "Exit current mode and down to previous mode\n")
+{
+       return vtysh_exit(vty);
+}
+
+DEFUNSH(VTYSH_FABRICD, vtysh_quit_fabricd, vtysh_quit_fabricd_cmd, "quit",
+       "Exit current mode and down to previous mode\n")
+{
+       return vtysh_exit_fabricd(self, vty, argc, argv);
+}
+
 DEFUNSH(VTYSH_ALL, vtysh_exit_line_vty, vtysh_exit_line_vty_cmd, "exit",
        "Exit current mode and down to previous mode\n")
 {
@@ -1968,18 +2092,6 @@ DEFUNSH(VTYSH_ZEBRA, vtysh_pseudowire, vtysh_pseudowire_cmd,
        return CMD_SUCCESS;
 }
 
-/* TODO Implement "no interface command in isisd. */
-DEFSH(VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D
-             | VTYSH_EIGRPD,
-      vtysh_no_interface_cmd, "no interface IFNAME", NO_STR
-      "Delete a pseudo interface's configuration\n"
-      "Interface's name\n")
-
-DEFSH(VTYSH_ZEBRA, vtysh_no_interface_vrf_cmd, "no interface IFNAME vrf NAME",
-      NO_STR
-      "Delete a pseudo interface's configuration\n"
-      "Interface's name\n" VRF_CMD_HELP_STR)
-
 DEFUNSH(VTYSH_ZEBRA, vtysh_logicalrouter, vtysh_logicalrouter_cmd,
        "logical-router (1-65535) ns NAME",
        "Enable a logical-router\n"
@@ -2020,9 +2132,16 @@ DEFUNSH(VTYSH_VRF, vtysh_vrf, vtysh_vrf_cmd, "vrf NAME",
        return CMD_SUCCESS;
 }
 
-DEFSH(VTYSH_ZEBRA, vtysh_no_vrf_cmd, "no vrf NAME", NO_STR
-      "Delete a pseudo vrf's configuration\n"
-      "VRF's name\n")
+DEFSH(VTYSH_ZEBRA, vtysh_vrf_netns_cmd,
+      "netns NAME",
+      "Attach VRF to a Namespace\n"
+      "The file name in " NS_RUN_DIR ", or a full pathname\n")
+
+DEFSH(VTYSH_ZEBRA, vtysh_no_vrf_netns_cmd,
+      "no netns [NAME]",
+      NO_STR
+      "Detach VRF from a Namespace\n"
+      "The file name in " NS_RUN_DIR ", or a full pathname\n")
 
 DEFUNSH(VTYSH_NS, vtysh_exit_logicalrouter,
        vtysh_exit_logicalrouter_cmd, "exit",
@@ -2062,19 +2181,6 @@ DEFUNSH(VTYSH_VRF, vtysh_quit_nexthop_group, vtysh_quit_nexthop_group_cmd,
        return vtysh_exit_nexthop_group(self, vty, argc, argv);
 }
 
-/*
- * TODO Implement interface description commands in ripngd, ospf6d
- * and isisd.
- */
-DEFSH(VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_OSPFD | VTYSH_EIGRPD,
-      vtysh_interface_desc_cmd, "description LINE...",
-      "Interface specific description\n"
-      "Characters describing this interface\n")
-
-DEFSH(VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_OSPFD | VTYSH_EIGRPD,
-      vtysh_no_interface_desc_cmd, "no description",
-      NO_STR "Interface specific description\n")
-
 DEFUNSH(VTYSH_INTERFACE, vtysh_exit_interface, vtysh_exit_interface_cmd, "exit",
        "Exit current mode and down to previous mode\n")
 {
@@ -2087,6 +2193,28 @@ DEFUNSH(VTYSH_INTERFACE, vtysh_quit_interface, vtysh_quit_interface_cmd, "quit",
        return vtysh_exit_interface(self, vty, argc, argv);
 }
 
+DEFUN (vtysh_show_poll,
+       vtysh_show_poll_cmd,
+       "show thread poll",
+       SHOW_STR
+       "Thread information\n"
+       "Thread Poll Information\n")
+{
+       unsigned int i;
+       int ret = CMD_SUCCESS;
+       char line[100];
+
+       snprintf(line, sizeof(line), "do show thread poll\n");
+       for (i = 0; i < array_size(vtysh_client); i++)
+               if (vtysh_client[i].fd >= 0) {
+                       vty_out(vty, "Thread statistics for %s:\n",
+                               vtysh_client[i].name);
+                       ret = vtysh_client_execute(&vtysh_client[i], line);
+                       vty_out(vty, "\n");
+               }
+       return ret;
+}
+
 DEFUN (vtysh_show_thread,
        vtysh_show_thread_cmd,
        "show thread cpu [FILTER]",
@@ -2106,11 +2234,10 @@ DEFUN (vtysh_show_thread,
        snprintf(line, sizeof(line), "do show thread cpu %s\n", filter);
        for (i = 0; i < array_size(vtysh_client); i++)
                if (vtysh_client[i].fd >= 0) {
-                       fprintf(stdout, "Thread statistics for %s:\n",
+                       vty_out(vty, "Thread statistics for %s:\n",
                                vtysh_client[i].name);
-                       ret = vtysh_client_execute(&vtysh_client[i], line,
-                                                  outputfile);
-                       fprintf(stdout, "\n");
+                       ret = vtysh_client_execute(&vtysh_client[i], line);
+                       vty_out(vty, "\n");
                }
        return ret;
 }
@@ -2127,11 +2254,10 @@ DEFUN (vtysh_show_work_queues,
 
        for (i = 0; i < array_size(vtysh_client); i++)
                if (vtysh_client[i].fd >= 0) {
-                       fprintf(stdout, "Work queue statistics for %s:\n",
+                       vty_out(vty, "Work queue statistics for %s:\n",
                                vtysh_client[i].name);
-                       ret = vtysh_client_execute(&vtysh_client[i], line,
-                                                  outputfile);
-                       fprintf(stdout, "\n");
+                       ret = vtysh_client_execute(&vtysh_client[i], line);
+                       vty_out(vty, "\n");
                }
 
        return ret;
@@ -2139,7 +2265,7 @@ DEFUN (vtysh_show_work_queues,
 
 DEFUN (vtysh_show_work_queues_daemon,
        vtysh_show_work_queues_daemon_cmd,
-       "show work-queues <zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|pbrd>",
+       "show work-queues <zebra|ripd|ripngd|ospfd|ospf6d|bgpd|isisd|pbrd|fabricd|pimd|staticd>",
        SHOW_STR
        "Work Queue information\n"
        "For the zebra daemon\n"
@@ -2149,7 +2275,10 @@ DEFUN (vtysh_show_work_queues_daemon,
        "For the ospfv6 daemon\n"
        "For the bgp daemon\n"
        "For the isis daemon\n"
-       "For the pbr daemon\n")
+       "For the pbr daemon\n"
+       "For the fabricd daemon\n"
+       "For the pim daemon\n"
+       "For the static daemon\n")
 {
        int idx_protocol = 2;
        unsigned int i;
@@ -2160,8 +2289,7 @@ DEFUN (vtysh_show_work_queues_daemon,
                        break;
        }
 
-       ret = vtysh_client_execute(&vtysh_client[i], "show work-queues\n",
-                                  outputfile);
+       ret = vtysh_client_execute(&vtysh_client[i], "show work-queues\n");
 
        return ret;
 }
@@ -2188,10 +2316,9 @@ static int show_per_daemon(const char *line, const char *headline)
 
        for (i = 0; i < array_size(vtysh_client); i++)
                if (vtysh_client[i].fd >= 0) {
-                       fprintf(outputfile, headline, vtysh_client[i].name);
-                       ret = vtysh_client_execute(&vtysh_client[i], line,
-                                                  outputfile);
-                       fprintf(stdout, "\n");
+                       vty_out(vty, headline, vtysh_client[i].name);
+                       ret = vtysh_client_execute(&vtysh_client[i], line);
+                       vty_out(vty, "\n");
                }
 
        return ret;
@@ -2225,21 +2352,43 @@ DEFUN (vtysh_show_debugging_hashtable,
        "Statistics about hash tables\n"
        "Statistics about hash tables\n")
 {
-       fprintf(stdout, "\n");
-       fprintf(stdout,
+       vty_out(vty, "\n");
+       vty_out(vty,
                "Load factor (LF) - average number of elements across all buckets\n");
-       fprintf(stdout,
+       vty_out(vty,
                "Full load factor (FLF) - average number of elements across full buckets\n\n");
-       fprintf(stdout,
+       vty_out(vty,
                "Standard deviation (SD) is calculated for both the LF and FLF\n");
-       fprintf(stdout,
+       vty_out(vty,
                "and indicates the typical deviation of bucket chain length\n");
-       fprintf(stdout, "from the value in the corresponding load factor.\n\n");
+       vty_out(vty, "from the value in the corresponding load factor.\n\n");
 
        return show_per_daemon("do show debugging hashtable\n",
                               "Hashtable statistics for %s:\n");
 }
 
+DEFUN (vtysh_show_error_code,
+       vtysh_show_error_code_cmd,
+       "show error <(1-4294967296)|all> [json]",
+       SHOW_STR
+       "Information on errors\n"
+       "Error code to get info about\n"
+       "Information on all errors\n"
+       JSON_STR)
+{
+       char *fcmd = argv_concat(argv, argc, 0);
+       char cmd[256];
+       int rv;
+
+       snprintf(cmd, sizeof(cmd), "do %s", fcmd);
+
+       /* FIXME: Needs to determine which daemon to send to via code ranges */
+       rv = show_per_daemon(cmd, "");
+
+       XFREE(MTYPE_TMP, fcmd);
+       return rv;
+}
+
 /* Memory */
 DEFUN (vtysh_show_memory,
        vtysh_show_memory_cmd,
@@ -2348,10 +2497,11 @@ DEFUNSH(VTYSH_ALL, vtysh_log_syslog, vtysh_log_syslog_cmd,
 }
 
 DEFUNSH(VTYSH_ALL, no_vtysh_log_syslog, no_vtysh_log_syslog_cmd,
-       "no log syslog [LEVEL]", NO_STR
+       "no log syslog [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
+       NO_STR
        "Logging control\n"
        "Cancel logging to syslog\n"
-       "Logging level\n")
+       LOG_LEVEL_DESC)
 {
        return CMD_SUCCESS;
 }
@@ -2373,24 +2523,6 @@ DEFUNSH(VTYSH_ALL, no_vtysh_log_facility, no_vtysh_log_facility_cmd,
        return CMD_SUCCESS;
 }
 
-DEFUNSH_DEPRECATED(
-       VTYSH_ALL, vtysh_log_trap, vtysh_log_trap_cmd,
-       "log trap <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>",
-       "Logging control\n"
-       "(Deprecated) Set logging level and default for all destinations\n" LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH_DEPRECATED(VTYSH_ALL, no_vtysh_log_trap, no_vtysh_log_trap_cmd,
-                  "no log trap [LEVEL]", NO_STR
-                  "Logging control\n"
-                  "Permit all logging information\n"
-                  "Logging level\n")
-{
-       return CMD_SUCCESS;
-}
-
 DEFUNSH(VTYSH_ALL, vtysh_log_record_priority, vtysh_log_record_priority_cmd,
        "log record-priority",
        "Logging control\n"
@@ -2484,7 +2616,7 @@ DEFUNSH(VTYSH_ALL, no_vtysh_config_enable_password,
 
 DEFUN (vtysh_write_terminal,
        vtysh_write_terminal_cmd,
-       "write terminal [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|pimd>]",
+       "write terminal [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|fabricd|pimd|staticd>]",
        "Write running configuration to memory, network, or terminal\n"
        "Write to terminal\n"
        "For the zebra daemon\n"
@@ -2495,23 +2627,16 @@ DEFUN (vtysh_write_terminal,
        "For the ldpd daemon\n"
        "For the bgp daemon\n"
        "For the isis daemon\n"
-       "For the pim daemon\n")
+       "For the fabricd daemon\n"
+       "For the pim daemon\n"
+       "For the static daemon\n")
 {
        unsigned int i;
        char line[] = "do write terminal\n";
-       FILE *fp = outputfile;
 
-       if (fp == stdout && vtysh_pager_name) {
-               fp = popen(vtysh_pager_name, "w");
-               if (fp == NULL) {
-                       perror("popen");
-                       exit(1);
-               }
-       }
-
-       fprintf(outputfile, "Building configuration...\n");
-       fprintf(outputfile, "\nCurrent configuration:\n");
-       fprintf(outputfile, "!\n");
+       vty_out(vty, "Building configuration...\n");
+       vty_out(vty, "\nCurrent configuration:\n");
+       vty_out(vty, "!\n");
 
        for (i = 0; i < array_size(vtysh_client); i++)
                if ((argc < 3)
@@ -2519,26 +2644,18 @@ DEFUN (vtysh_write_terminal,
                        vtysh_client_config(&vtysh_client[i], line);
 
        /* Integrate vtysh specific configuration. */
+       vty_open_pager(vty);
        vtysh_config_write();
+       vtysh_config_dump();
+       vty_close_pager(vty);
+       vty_out(vty, "end\n");
 
-       vtysh_config_dump(fp);
-
-       if (vtysh_pager_name && fp != outputfile) {
-               fflush(fp);
-               if (pclose(fp) == -1) {
-                       perror("pclose");
-                       exit(1);
-               }
-               fp = NULL;
-       }
-
-       fprintf(outputfile, "end\n");
        return CMD_SUCCESS;
 }
 
 DEFUN (vtysh_show_running_config,
        vtysh_show_running_config_cmd,
-       "show running-config [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|pimd>]",
+       "show running-config [<zebra|ripd|ripngd|ospfd|ospf6d|ldpd|bgpd|isisd|fabricd|pimd|staticd>]",
        SHOW_STR
        "Current operating configuration\n"
        "For the zebra daemon\n"
@@ -2549,7 +2666,9 @@ DEFUN (vtysh_show_running_config,
        "For the ldp daemon\n"
        "For the bgp daemon\n"
        "For the isis daemon\n"
-       "For the pim daemon\n")
+       "For the fabricd daemon\n"
+       "For the pim daemon\n"
+       "For the static daemon\n")
 {
        return vtysh_write_terminal(self, vty, argc, argv);
 }
@@ -2584,8 +2703,13 @@ static void backup_config_file(const char *fbackup)
        strcat(integrate_sav, CONF_BACKUP_EXT);
 
        /* Move current configuration file to backup config file. */
-       unlink(integrate_sav);
-       rename(fbackup, integrate_sav);
+       if (unlink(integrate_sav) != 0) {
+               vty_out(vty, "Warning: %s unlink failed\n", integrate_sav);
+       }
+       if (rename(fbackup, integrate_sav) != 0) {
+               vty_out(vty, "Error renaming %s to %s\n", fbackup,
+                       integrate_sav);
+       }
        free(integrate_sav);
 }
 
@@ -2595,19 +2719,23 @@ int vtysh_write_config_integrated(void)
        char line[] = "do write terminal\n";
        FILE *fp;
        int fd;
+#ifdef FRR_USER
        struct passwd *pwentry;
+#endif
+#ifdef FRR_GROUP
        struct group *grentry;
+#endif
        uid_t uid = -1;
        gid_t gid = -1;
        struct stat st;
        int err = 0;
 
-       fprintf(stdout, "Building Configuration...\n");
+       vty_out(vty, "Building Configuration...\n");
 
        backup_config_file(frr_config);
        fp = fopen(frr_config, "w");
        if (fp == NULL) {
-               fprintf(stdout,
+               vty_out(vty,
                        "%% Error: failed to open configuration file %s: %s\n",
                        frr_config, safe_strerror(errno));
                return CMD_WARNING_CONFIG_FAILED;
@@ -2618,7 +2746,10 @@ int vtysh_write_config_integrated(void)
                vtysh_client_config(&vtysh_client[i], line);
 
        vtysh_config_write();
-       vtysh_config_dump(fp);
+       vty->of_saved = vty->of;
+       vty->of = fp;
+       vtysh_config_dump();
+       vty->of = vty->of_saved;
 
        if (fchmod(fd, CONFIGFILE_MASK) != 0) {
                printf("%% Warning: can't chmod configuration file %s: %s\n",
@@ -2701,8 +2832,7 @@ DEFUN (vtysh_write_memory,
        char line[] = "do write memory\n";
        unsigned int i;
 
-       fprintf(outputfile,
-               "Note: this version of vtysh never writes vtysh.conf\n");
+       vty_out(vty, "Note: this version of vtysh never writes vtysh.conf\n");
 
        /* If integrated frr.conf explicitely set. */
        if (want_config_integrated()) {
@@ -2717,8 +2847,7 @@ DEFUN (vtysh_write_memory,
                if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1) {
                        used_watchfrr = true;
                        ret = vtysh_client_execute(&vtysh_client[i],
-                                                  "do write integrated",
-                                                  outputfile);
+                                                  "do write integrated");
                }
 
                /*
@@ -2734,10 +2863,10 @@ DEFUN (vtysh_write_memory,
                return ret;
        }
 
-       fprintf(outputfile, "Building Configuration...\n");
+       vty_out(vty, "Building Configuration...\n");
 
        for (i = 0; i < array_size(vtysh_client); i++)
-               ret = vtysh_client_execute(&vtysh_client[i], line, outputfile);
+               ret = vtysh_client_execute(&vtysh_client[i], line);
 
        return ret;
 }
@@ -2752,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') {
-               fprintf(outputfile, "length is malformed\n");
-               return CMD_WARNING;
-       }
+       free(vtysh_pager_name);
+       vtysh_pager_name = NULL;
 
-       if (vtysh_pager_name) {
-               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,
@@ -2809,8 +2944,8 @@ DEFUN (vtysh_show_daemons,
 
        for (i = 0; i < array_size(vtysh_client); i++)
                if (vtysh_client[i].fd >= 0)
-                       fprintf(outputfile, " %s", vtysh_client[i].name);
-       fprintf(outputfile, "\n");
+                       vty_out(vty, " %s", vtysh_client[i].name);
+       vty_out(vty, "\n");
 
        return CMD_SUCCESS;
 }
@@ -3007,11 +3142,11 @@ DEFUN (vtysh_output_file,
        "Path to dump output to\n")
 {
        const char *path = argv[argc - 1]->arg;
-       outputfile = fopen(path, "a");
-       if (!outputfile) {
-               fprintf(stdout, "Failed to open file '%s': %s\n", path,
+       vty->of = fopen(path, "a");
+       if (!vty->of) {
+               vty_out(vty, "Failed to open file '%s': %s\n", path,
                        safe_strerror(errno));
-               outputfile = stdout;
+               vty->of = stdout;
        }
        return CMD_SUCCESS;
 }
@@ -3024,9 +3159,9 @@ DEFUN (no_vtysh_output_file,
        "Direct vtysh output to file\n"
        "Path to dump output to\n")
 {
-       if (outputfile != stdout) {
-               fclose(outputfile);
-               outputfile = stdout;
+       if (vty->of != stdout) {
+               fclose(vty->of);
+               vty->of = stdout;
        }
        return CMD_SUCCESS;
 }
@@ -3050,7 +3185,7 @@ DEFUN(find,
                for (unsigned int j = 0; j < vector_active(clis); j++) {
                        cli = vector_slot(clis, j);
                        if (strcasestr(cli->string, text))
-                               fprintf(stdout, "  (%s)  %s\n",
+                               vty_out(vty, "  (%s)  %s\n",
                                        node_names[node->node], cli->string);
                }
        }
@@ -3157,7 +3292,7 @@ static int vtysh_reconnect(struct vtysh_client *vclient)
                return ret;
        }
        fprintf(stderr, "success!\n");
-       if (vtysh_client_execute(vclient, "enable", NULL) < 0)
+       if (vtysh_client_execute(vclient, "enable") < 0)
                return -1;
        return vtysh_execute_no_pager("end");
 }
@@ -3284,8 +3419,7 @@ void vtysh_readline_init(void)
        rl_initialize();
        rl_bind_key('?', (rl_command_func_t *)vtysh_rl_describe);
        rl_completion_entry_function = vtysh_completion_entry_function;
-       rl_attempted_completion_function =
-               (rl_completion_func_t *)new_completion;
+       rl_attempted_completion_function = new_completion;
 }
 
 char *vtysh_prompt(void)
@@ -3314,9 +3448,12 @@ static void vtysh_autocomplete(vector comps, struct cmd_token *token)
        snprintf(accmd, sizeof(accmd), "autocomplete %d %s %s", token->type,
                 token->text, token->varname ? token->varname : "-");
 
+       vty->of_saved = vty->of;
+       vty->of = NULL;
        for (i = 0; i < array_size(vtysh_client); i++)
-               vtysh_client_run_all(&vtysh_client[i], accmd, 1, NULL,
-                                    vtysh_ac_line, comps);
+               vtysh_client_run_all(&vtysh_client[i], accmd, 1, vtysh_ac_line,
+                                    comps);
+       vty->of = vty->of_saved;
 }
 
 static const struct cmd_variable_handler vtysh_var_handler[] = {
@@ -3328,8 +3465,8 @@ static const struct cmd_variable_handler vtysh_var_handler[] = {
 
 void vtysh_uninit()
 {
-       if (outputfile != stdout)
-               fclose(outputfile);
+       if (vty->of != stdout)
+               fclose(vty->of);
 }
 
 void vtysh_init_vty(void)
@@ -3340,7 +3477,7 @@ void vtysh_init_vty(void)
        vty->node = VIEW_NODE;
 
        /* set default output */
-       outputfile = stdout;
+       vty->of = stdout;
 
        /* Initialize commands. */
        cmd_init(0);
@@ -3389,10 +3526,13 @@ void vtysh_init_vty(void)
        install_node(&keychain_node, NULL);
        install_node(&keychain_key_node, NULL);
        install_node(&isis_node, NULL);
+       install_node(&openfabric_node, NULL);
        install_node(&vty_node, NULL);
-#if defined(HAVE_RPKI)
        install_node(&rpki_node, NULL);
-#endif
+#if HAVE_BFDD > 0
+       install_node(&bfd_node, NULL);
+       install_node(&bfd_peer_node, NULL);
+#endif /* HAVE_BFDD */
 
        struct cmd_node *node;
        for (unsigned int i = 0; i < vector_active(cmdvec); i++) {
@@ -3479,6 +3619,8 @@ void vtysh_init_vty(void)
 #endif
        install_element(ISIS_NODE, &vtysh_exit_isisd_cmd);
        install_element(ISIS_NODE, &vtysh_quit_isisd_cmd);
+       install_element(OPENFABRIC_NODE, &vtysh_exit_fabricd_cmd);
+       install_element(OPENFABRIC_NODE, &vtysh_quit_fabricd_cmd);
        install_element(KEYCHAIN_NODE, &vtysh_exit_ripd_cmd);
        install_element(KEYCHAIN_NODE, &vtysh_quit_ripd_cmd);
        install_element(KEYCHAIN_KEY_NODE, &vtysh_exit_ripd_cmd);
@@ -3487,6 +3629,21 @@ void vtysh_init_vty(void)
        install_element(RMAP_NODE, &vtysh_quit_rmap_cmd);
        install_element(PBRMAP_NODE, &vtysh_exit_pbr_map_cmd);
        install_element(PBRMAP_NODE, &vtysh_quit_pbr_map_cmd);
+#if HAVE_BFDD > 0
+       /* Enter node. */
+       install_element(CONFIG_NODE, &bfd_enter_cmd);
+       install_element(BFD_NODE, &bfd_peer_enter_cmd);
+
+       /* Exit/quit node. */
+       install_element(BFD_NODE, &vtysh_exit_bfdd_cmd);
+       install_element(BFD_NODE, &vtysh_quit_bfdd_cmd);
+       install_element(BFD_PEER_NODE, &vtysh_exit_bfdd_cmd);
+       install_element(BFD_PEER_NODE, &vtysh_quit_bfdd_cmd);
+
+       /* End/exit all. */
+       install_element(BFD_NODE, &vtysh_end_all_cmd);
+       install_element(BFD_PEER_NODE, &vtysh_end_all_cmd);
+#endif /* HAVE_BFDD */
        install_element(VTY_NODE, &vtysh_exit_line_vty_cmd);
        install_element(VTY_NODE, &vtysh_quit_line_vty_cmd);
 
@@ -3524,14 +3681,13 @@ void vtysh_init_vty(void)
        install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd);
        install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd);
        install_element(ISIS_NODE, &vtysh_end_all_cmd);
+       install_element(OPENFABRIC_NODE, &vtysh_end_all_cmd);
        install_element(KEYCHAIN_NODE, &vtysh_end_all_cmd);
        install_element(KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
        install_element(RMAP_NODE, &vtysh_end_all_cmd);
        install_element(PBRMAP_NODE, &vtysh_end_all_cmd);
        install_element(VTY_NODE, &vtysh_end_all_cmd);
 
-       install_element(INTERFACE_NODE, &vtysh_interface_desc_cmd);
-       install_element(INTERFACE_NODE, &vtysh_no_interface_desc_cmd);
        install_element(INTERFACE_NODE, &vtysh_end_all_cmd);
        install_element(INTERFACE_NODE, &vtysh_exit_interface_cmd);
        install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
@@ -3575,6 +3731,7 @@ void vtysh_init_vty(void)
        install_element(LDP_L2VPN_NODE, &ldp_member_pseudowire_ifname_cmd);
 #endif
        install_element(CONFIG_NODE, &router_isis_cmd);
+       install_element(CONFIG_NODE, &router_openfabric_cmd);
        install_element(CONFIG_NODE, &router_bgp_cmd);
        install_element(BGP_NODE, &address_family_vpnv4_cmd);
        install_element(BGP_NODE, &address_family_vpnv6_cmd);
@@ -3610,12 +3767,10 @@ void vtysh_init_vty(void)
        install_element(BGP_FLOWSPECV4_NODE, &exit_address_family_cmd);
        install_element(BGP_FLOWSPECV6_NODE, &exit_address_family_cmd);
 
-#if defined(HAVE_RPKI)
        install_element(CONFIG_NODE, &rpki_cmd);
        install_element(RPKI_NODE, &rpki_exit_cmd);
        install_element(RPKI_NODE, &rpki_quit_cmd);
        install_element(RPKI_NODE, &vtysh_end_all_cmd);
-#endif
 
        /* EVPN commands */
        install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
@@ -3635,17 +3790,16 @@ void vtysh_init_vty(void)
        install_element(KEYCHAIN_NODE, &key_chain_cmd);
        install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd);
        install_element(CONFIG_NODE, &vtysh_interface_cmd);
-       install_element(CONFIG_NODE, &vtysh_no_interface_cmd);
-       install_element(CONFIG_NODE, &vtysh_no_interface_vrf_cmd);
        install_element(CONFIG_NODE, &vtysh_pseudowire_cmd);
        install_element(INTERFACE_NODE, &vtysh_link_params_cmd);
        install_element(ENABLE_NODE, &vtysh_show_running_config_cmd);
        install_element(ENABLE_NODE, &vtysh_copy_running_config_cmd);
 
+       install_element(CONFIG_NODE, &vtysh_vrf_cmd);
+       install_element(VRF_NODE, &vtysh_vrf_netns_cmd);
+       install_element(VRF_NODE, &vtysh_no_vrf_netns_cmd);
        install_element(VRF_NODE, &exit_vrf_config_cmd);
 
-       install_element(CONFIG_NODE, &vtysh_vrf_cmd);
-       install_element(CONFIG_NODE, &vtysh_no_vrf_cmd);
        install_element(CONFIG_NODE, &vtysh_no_nexthop_group_cmd);
 
        /* "write terminal" command. */
@@ -3657,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);
@@ -3681,6 +3836,7 @@ void vtysh_init_vty(void)
 
        /* debugging */
        install_element(VIEW_NODE, &vtysh_show_debugging_cmd);
+       install_element(VIEW_NODE, &vtysh_show_error_code_cmd);
        install_element(VIEW_NODE, &vtysh_show_debugging_hashtable_cmd);
        install_element(ENABLE_NODE, &vtysh_debug_all_cmd);
        install_element(CONFIG_NODE, &vtysh_debug_all_cmd);
@@ -3691,6 +3847,7 @@ void vtysh_init_vty(void)
        install_element(VIEW_NODE, &vtysh_show_work_queues_cmd);
        install_element(VIEW_NODE, &vtysh_show_work_queues_daemon_cmd);
        install_element(VIEW_NODE, &vtysh_show_thread_cmd);
+       install_element(VIEW_NODE, &vtysh_show_poll_cmd);
 
        /* Logging */
        install_element(VIEW_NODE, &vtysh_show_logging_cmd);
@@ -3704,8 +3861,6 @@ void vtysh_init_vty(void)
        install_element(CONFIG_NODE, &no_vtysh_log_monitor_cmd);
        install_element(CONFIG_NODE, &vtysh_log_syslog_cmd);
        install_element(CONFIG_NODE, &no_vtysh_log_syslog_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_trap_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_trap_cmd);
        install_element(CONFIG_NODE, &vtysh_log_facility_cmd);
        install_element(CONFIG_NODE, &no_vtysh_log_facility_cmd);
        install_element(CONFIG_NODE, &vtysh_log_record_priority_cmd);