back to topotato report
topotato coverage report
Current view: top level - vtysh - vtysh.c (source / functions) Hit Total Coverage
Test: test_pim6_bootstrap.py::PIM6Bootstrap Lines: 652 1945 33.5 %
Date: 2023-02-16 02:07:22 Functions: 25 226 11.1 %

          Line data    Source code
       1             : /* Virtual terminal interface shell.
       2             :  * Copyright (C) 2000 Kunihiro Ishiguro
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include <sys/un.h>
      24             : #include <setjmp.h>
      25             : #include <sys/wait.h>
      26             : #include <sys/resource.h>
      27             : #include <sys/stat.h>
      28             : 
      29             : /* readline carries some ancient definitions around */
      30             : #pragma GCC diagnostic push
      31             : #pragma GCC diagnostic ignored "-Wstrict-prototypes"
      32             : #include <readline/readline.h>
      33             : #include <readline/history.h>
      34             : #pragma GCC diagnostic pop
      35             : 
      36             : #include <dirent.h>
      37             : #include <stdio.h>
      38             : #include <string.h>
      39             : 
      40             : #include "linklist.h"
      41             : #include "command.h"
      42             : #include "memory.h"
      43             : #include "network.h"
      44             : #include "filter.h"
      45             : #include "vtysh/vtysh.h"
      46             : #include "vtysh/vtysh_daemons.h"
      47             : #include "log.h"
      48             : #include "vrf.h"
      49             : #include "libfrr.h"
      50             : #include "command_graph.h"
      51             : #include "frrstr.h"
      52             : #include "json.h"
      53             : #include "ferr.h"
      54             : #include "bgpd/bgp_vty.h"
      55             : 
      56           2 : DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy");
      57             : 
      58             : /* Struct VTY. */
      59             : struct vty *vty;
      60             : 
      61             : /* VTY shell pager name. */
      62             : char *vtysh_pager_name = NULL;
      63             : 
      64             : /* VTY should add timestamp */
      65             : bool vtysh_add_timestamp;
      66             : 
      67             : /* VTY shell client structure */
      68             : struct vtysh_client {
      69             :         int fd;
      70             :         const char *name;
      71             :         int flag;
      72             :         char path[MAXPATHLEN];
      73             :         struct vtysh_client *next;
      74             : 
      75             :         struct thread *log_reader;
      76             :         int log_fd;
      77             :         uint32_t lost_msgs;
      78             : };
      79             : 
      80             : static bool stderr_tty;
      81             : static bool stderr_stdout_same;
      82             : 
      83             : /* Some utility functions for working on vtysh-specific vty tasks */
      84             : 
      85           0 : static FILE *vty_open_pager(struct vty *vty)
      86             : {
      87           0 :         if (vty->is_paged)
      88           0 :                 return vty->of;
      89             : 
      90           0 :         if (!vtysh_pager_name)
      91             :                 return NULL;
      92             : 
      93           0 :         vty->of_saved = vty->of;
      94           0 :         vty->of = popen(vtysh_pager_name, "w");
      95           0 :         if (vty->of == NULL) {
      96           0 :                 vty->of = vty->of_saved;
      97           0 :                 perror("popen");
      98           0 :                 exit(1);
      99             :         }
     100             : 
     101           0 :         vty->is_paged = true;
     102             : 
     103           0 :         return vty->of;
     104             : }
     105             : 
     106           0 : static int vty_close_pager(struct vty *vty)
     107             : {
     108           0 :         if (!vty->is_paged)
     109             :                 return 0;
     110             : 
     111           0 :         fflush(vty->of);
     112           0 :         if (pclose(vty->of) == -1) {
     113           0 :                 perror("pclose");
     114           0 :                 exit(1);
     115             :         }
     116             : 
     117           0 :         vty->of = vty->of_saved;
     118           0 :         vty->is_paged = false;
     119             : 
     120           0 :         return 0;
     121             : }
     122             : 
     123           1 : static void vtysh_pager_envdef(bool fallback)
     124             : {
     125           1 :         char *pager_defined;
     126             : 
     127           1 :         pager_defined = getenv("VTYSH_PAGER");
     128             : 
     129           1 :         if (pager_defined)
     130           0 :                 vtysh_pager_name = strdup(pager_defined);
     131           1 :         else if (fallback)
     132           0 :                 vtysh_pager_name = strdup(VTYSH_PAGER);
     133           1 : }
     134             : 
     135             : /* --- */
     136             : 
     137             : struct vtysh_client vtysh_client[] = {
     138             :         {.name = "zebra", .flag = VTYSH_ZEBRA},
     139             :         {.name = "ripd", .flag = VTYSH_RIPD},
     140             :         {.name = "ripngd", .flag = VTYSH_RIPNGD},
     141             :         {.name = "ospfd", .flag = VTYSH_OSPFD},
     142             :         {.name = "ospf6d", .flag = VTYSH_OSPF6D},
     143             :         {.name = "ldpd", .flag = VTYSH_LDPD},
     144             :         {.name = "bgpd", .flag = VTYSH_BGPD},
     145             :         {.name = "isisd", .flag = VTYSH_ISISD},
     146             :         {.name = "pimd", .flag = VTYSH_PIMD},
     147             :         {.name = "nhrpd", .flag = VTYSH_NHRPD},
     148             :         {.name = "eigrpd", .flag = VTYSH_EIGRPD},
     149             :         {.name = "babeld", .flag = VTYSH_BABELD},
     150             :         {.name = "sharpd", .flag = VTYSH_SHARPD},
     151             :         {.name = "fabricd", .flag = VTYSH_FABRICD},
     152             :         {.name = "watchfrr", .flag = VTYSH_WATCHFRR},
     153             :         {.name = "pbrd", .flag = VTYSH_PBRD},
     154             :         {.name = "staticd", .flag = VTYSH_STATICD},
     155             :         {.name = "bfdd", .flag = VTYSH_BFDD},
     156             :         {.name = "vrrpd", .flag = VTYSH_VRRPD},
     157             :         {.name = "pathd", .flag = VTYSH_PATHD},
     158             :         {.name = "pim6d", .flag = VTYSH_PIM6D},
     159             : };
     160             : 
     161             : /* Searches for client by name, returns index */
     162           0 : static int vtysh_client_lookup(const char *name)
     163             : {
     164           0 :         int idx = -1;
     165             : 
     166           0 :         for (unsigned int i = 0; i < array_size(vtysh_client); i++) {
     167           0 :                 if (strmatch(vtysh_client[i].name, name)) {
     168           0 :                         idx = i;
     169           0 :                         break;
     170             :                 }
     171             :         }
     172             : 
     173           0 :         return idx;
     174             : }
     175             : 
     176             : enum vtysh_write_integrated vtysh_write_integrated =
     177             :         WRITE_INTEGRATED_UNSPECIFIED;
     178             : 
     179             : static int vtysh_reconnect(struct vtysh_client *vclient);
     180             : 
     181           0 : static void vclient_close(struct vtysh_client *vclient)
     182             : {
     183           0 :         if (vclient->fd >= 0) {
     184           0 :                 if (vty->of)
     185           0 :                         vty_out(vty,
     186             :                                 "Warning: closing connection to %s because of an I/O error!\n",
     187             :                                 vclient->name);
     188           0 :                 close(vclient->fd);
     189             :                 /* indicate as candidate for reconnect */
     190           0 :                 vclient->fd = VTYSH_WAS_ACTIVE;
     191             :         }
     192           0 : }
     193             : 
     194          10 : static ssize_t vtysh_client_receive(struct vtysh_client *vclient, char *buf,
     195             :                                     size_t bufsz, int *pass_fd)
     196             : {
     197          10 :         struct iovec iov[1] = {
     198             :                 {
     199             :                         .iov_base = buf,
     200             :                         .iov_len = bufsz,
     201             :                 },
     202             :         };
     203          10 :         union {
     204             :                 uint8_t buf[CMSG_SPACE(sizeof(int))];
     205             :                 struct cmsghdr align;
     206             :         } u;
     207          10 :         struct msghdr mh = {
     208             :                 .msg_iov = iov,
     209             :                 .msg_iovlen = array_size(iov),
     210             :                 .msg_control = u.buf,
     211             :                 .msg_controllen = sizeof(u.buf),
     212             :         };
     213          10 :         struct cmsghdr *cmh = CMSG_FIRSTHDR(&mh);
     214          10 :         ssize_t ret;
     215             : 
     216          10 :         cmh->cmsg_level = SOL_SOCKET;
     217          10 :         cmh->cmsg_type = SCM_RIGHTS;
     218          10 :         cmh->cmsg_len = CMSG_LEN(sizeof(int));
     219          10 :         memset(CMSG_DATA(cmh), -1, sizeof(int));
     220             : 
     221          10 :         do {
     222          10 :                 ret = recvmsg(vclient->fd, &mh, 0);
     223          10 :                 if (ret >= 0 || (errno != EINTR && errno != EAGAIN))
     224             :                         break;
     225             :         } while (true);
     226             : 
     227          10 :         if (cmh->cmsg_len == CMSG_LEN(sizeof(int))) {
     228          10 :                 int fd;
     229             : 
     230          10 :                 memcpy(&fd, CMSG_DATA(cmh), sizeof(int));
     231          10 :                 if (fd != -1) {
     232           0 :                         if (pass_fd)
     233           0 :                                 *pass_fd = fd;
     234             :                         else
     235           0 :                                 close(fd);
     236             :                 }
     237             :         }
     238          10 :         return ret;
     239             : }
     240             : 
     241             : /*
     242             :  * Send a CLI command to a client and read the response.
     243             :  *
     244             :  * Output will be printed to vty->of. If you want to suppress output, set that
     245             :  * to NULL.
     246             :  *
     247             :  * vclient
     248             :  *    the client to send the command to
     249             :  *
     250             :  * line
     251             :  *    the command to send
     252             :  *
     253             :  * callback
     254             :  *    if non-null, this will be called with each line of output received from
     255             :  *    the client passed in the second parameter
     256             :  *
     257             :  * cbarg
     258             :  *    optional first argument to pass to callback
     259             :  *
     260             :  * Returns:
     261             :  *    a status code
     262             :  */
     263         332 : static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
     264             :                             void (*callback)(void *, const char *), void *cbarg,
     265             :                             int *pass_fd)
     266             : {
     267         332 :         int ret;
     268         332 :         char stackbuf[4096];
     269         332 :         char *buf = stackbuf;
     270         332 :         size_t bufsz = sizeof(stackbuf);
     271         332 :         char *bufvalid, *end = NULL;
     272         332 :         char terminator[3] = {0, 0, 0};
     273             : 
     274             :         /* vclinet was previously active, try to reconnect */
     275         332 :         if (vclient->fd == VTYSH_WAS_ACTIVE) {
     276           0 :                 ret = vtysh_reconnect(vclient);
     277           0 :                 if (ret < 0)
     278           0 :                         goto out_err;
     279             :         }
     280             : 
     281         332 :         if (vclient->fd < 0)
     282             :                 return CMD_SUCCESS;
     283             : 
     284          10 :         ret = write(vclient->fd, line, strlen(line) + 1);
     285          10 :         if (ret <= 0) {
     286             :                 /* close connection and try to reconnect */
     287           0 :                 vclient_close(vclient);
     288           0 :                 ret = vtysh_reconnect(vclient);
     289           0 :                 if (ret < 0)
     290           0 :                         goto out_err;
     291             :                 /* retry line */
     292           0 :                 ret = write(vclient->fd, line, strlen(line) + 1);
     293           0 :                 if (ret <= 0)
     294           0 :                         goto out_err;
     295             :         }
     296             : 
     297             :         bufvalid = buf;
     298          10 :         do {
     299          10 :                 ssize_t nread;
     300             : 
     301          20 :                 nread = vtysh_client_receive(
     302          10 :                         vclient, bufvalid, buf + bufsz - bufvalid - 1, pass_fd);
     303             : 
     304          10 :                 if (nread < 0 && (errno == EINTR || errno == EAGAIN))
     305           0 :                         continue;
     306             : 
     307          10 :                 if (nread <= 0) {
     308           0 :                         if (vty->of)
     309           0 :                                 vty_out(vty,
     310             :                                         "vtysh: error reading from %s: %s (%d)",
     311             :                                         vclient->name, safe_strerror(errno),
     312           0 :                                         errno);
     313           0 :                         goto out_err;
     314             :                 }
     315             : 
     316          10 :                 bufvalid += nread;
     317             : 
     318             :                 /* Null terminate so we may pass this to *printf later. */
     319          10 :                 bufvalid[0] = '\0';
     320             : 
     321             :                 /*
     322             :                  * We expect string output from daemons, so instead of looking
     323             :                  * for the full 3 null bytes of the terminator, we check for
     324             :                  * just one instead and assume it is the first byte of the
     325             :                  * terminator. The presence of the full terminator is checked
     326             :                  * later.
     327             :                  */
     328          10 :                 if (bufvalid - buf >= 4)
     329          10 :                         end = memmem(bufvalid - 4, 4, "\0", 1);
     330             : 
     331             :                 /*
     332             :                  * calculate # bytes we have, up to & not including the
     333             :                  * terminator if present
     334             :                  */
     335          10 :                 size_t textlen = (end ? end : bufvalid) - buf;
     336          10 :                 bool b = false;
     337             : 
     338             :                 /* feed line processing callback if present */
     339          10 :                 while (callback && bufvalid > buf && (end > buf || !end)) {
     340           0 :                         textlen = (end ? end : bufvalid) - buf;
     341           0 :                         char *eol = memchr(buf, '\n', textlen);
     342           0 :                         if (eol)
     343             :                                 /* line break */
     344           0 :                                 *eol++ = '\0';
     345           0 :                         else if (end == buf)
     346             :                                 /*
     347             :                                  * no line break, end of input, no text left
     348             :                                  * before end; nothing to write
     349             :                                  */
     350             :                                 b = true;
     351           0 :                         else if (end)
     352             :                                 /* no nl, end of input, but some text left */
     353             :                                 eol = end;
     354           0 :                         else if (bufvalid == buf + bufsz - 1) {
     355             :                                 /*
     356             :                                  * no nl, no end of input, no buffer space;
     357             :                                  * realloc
     358             :                                  */
     359           0 :                                 char *new;
     360             : 
     361           0 :                                 bufsz *= 2;
     362           0 :                                 if (buf == stackbuf) {
     363           0 :                                         new = XMALLOC(MTYPE_TMP, bufsz);
     364           0 :                                         memcpy(new, stackbuf, sizeof(stackbuf));
     365             :                                 } else
     366           0 :                                         new = XREALLOC(MTYPE_TMP, buf, bufsz);
     367             : 
     368           0 :                                 bufvalid = bufvalid - buf + new;
     369           0 :                                 buf = new;
     370             :                                 /* if end != NULL, we won't be reading more
     371             :                                  * data... */
     372           0 :                                 assert(end == NULL);
     373             :                                 b = true;
     374             :                         } else
     375             :                                 b = true;
     376             : 
     377           0 :                         if (b)
     378             :                                 break;
     379             : 
     380             :                         /* eol is at line end now, either \n => \0 or \0\0\0 */
     381           0 :                         assert(eol && eol <= bufvalid);
     382             : 
     383           0 :                         if (vty->of)
     384           0 :                                 vty_out(vty, "%s\n", buf);
     385             : 
     386           0 :                         callback(cbarg, buf);
     387             : 
     388             :                         /* shift back data and adjust bufvalid */
     389           0 :                         memmove(buf, eol, bufvalid - eol);
     390           0 :                         bufvalid -= eol - buf;
     391           0 :                         if (end)
     392           0 :                                 end -= eol - buf;
     393             :                 }
     394             : 
     395             :                 /* else if no callback, dump raw */
     396          10 :                 if (!callback) {
     397          10 :                         if (vty->of)
     398          10 :                                 vty_out(vty, "%s", buf);
     399          10 :                         memmove(buf, buf + textlen, bufvalid - buf - textlen);
     400          10 :                         bufvalid -= textlen;
     401          10 :                         if (end)
     402          10 :                                 end -= textlen;
     403             : 
     404             :                         /*
     405             :                          * ----------------------------------------------------
     406             :                          * At this point `buf` should be in one of two states:
     407             :                          * - Empty (i.e. buf == bufvalid)
     408             :                          * - Contains up to 4 bytes of the terminator
     409             :                          * ----------------------------------------------------
     410             :                          */
     411          10 :                         assert(((buf == bufvalid)
     412             :                                 || (bufvalid - buf <= 4 && buf[0] == 0x00)));
     413             :                 }
     414             : 
     415             :                 /* if we have the terminator, break */
     416          10 :                 if (end && bufvalid - buf == 4) {
     417          10 :                         assert(!memcmp(buf, terminator, 3));
     418          10 :                         ret = buf[3];
     419          10 :                         break;
     420             :                 }
     421             : 
     422             :         } while (true);
     423          10 :         goto out;
     424             : 
     425           0 : out_err:
     426           0 :         vclient_close(vclient);
     427           0 :         ret = CMD_SUCCESS;
     428          10 : out:
     429          10 :         if (buf != stackbuf)
     430           0 :                 XFREE(MTYPE_TMP, buf);
     431             :         return ret;
     432             : }
     433             : 
     434         332 : static int vtysh_client_run_all(struct vtysh_client *head_client,
     435             :                                 const char *line, int continue_on_err,
     436             :                                 void (*callback)(void *, const char *),
     437             :                                 void *cbarg)
     438             : {
     439         332 :         struct vtysh_client *client;
     440         332 :         int rc, rc_all = CMD_SUCCESS;
     441         332 :         int correct_instance = 0, wrong_instance = 0;
     442             : 
     443         664 :         for (client = head_client; client; client = client->next) {
     444         332 :                 rc = vtysh_client_run(client, line, callback, cbarg, NULL);
     445         332 :                 if (rc == CMD_NOT_MY_INSTANCE) {
     446           0 :                         wrong_instance++;
     447           0 :                         continue;
     448             :                 }
     449         332 :                 if (client->fd > 0)
     450          10 :                         correct_instance++;
     451         332 :                 if (rc != CMD_SUCCESS) {
     452           0 :                         if (!continue_on_err)
     453           0 :                                 return rc;
     454             :                         rc_all = rc;
     455             :                 }
     456             :         }
     457         332 :         if (wrong_instance && !correct_instance && vty->of) {
     458           0 :                 vty_out(vty,
     459             :                         "%% [%s]: command ignored as it targets an instance that is not running\n",
     460             :                         head_client->name);
     461           0 :                 rc_all = CMD_WARNING_CONFIG_FAILED;
     462             :         }
     463             :         return rc_all;
     464             : }
     465             : 
     466             : /*
     467             :  * Execute command against all daemons.
     468             :  *
     469             :  * head_client
     470             :  *    where to start walking in the daemon list
     471             :  *
     472             :  * line
     473             :  *    the specific command to execute
     474             :  *
     475             :  * Returns:
     476             :  *    a status code
     477             :  */
     478         332 : static int vtysh_client_execute(struct vtysh_client *head_client,
     479             :                                 const char *line)
     480             : {
     481         252 :         return vtysh_client_run_all(head_client, line, 0, NULL, NULL);
     482             : }
     483             : 
     484             : /* Execute by name */
     485           0 : static int vtysh_client_execute_name(const char *name, const char *line)
     486             : {
     487           0 :         int ret = CMD_SUCCESS;
     488           0 :         int idx_client = -1;
     489             : 
     490           0 :         idx_client = vtysh_client_lookup(name);
     491           0 :         if (idx_client != -1)
     492           0 :                 ret = vtysh_client_execute(&vtysh_client[idx_client], line);
     493             :         else {
     494           0 :                 vty_out(vty, "Client not found\n");
     495           0 :                 ret = CMD_WARNING;
     496             :         }
     497             : 
     498           0 :         return ret;
     499             : }
     500             : 
     501             : /*
     502             :  * Retrieve all running config from daemons and parse it with the vtysh config
     503             :  * parser. Returned output is not displayed to the user.
     504             :  *
     505             :  * head_client
     506             :  *    where to start walking in the daemon list
     507             :  *
     508             :  * line
     509             :  *    the specific command to execute
     510             :  */
     511           0 : static void vtysh_client_config(struct vtysh_client *head_client, char *line)
     512             : {
     513             :         /* watchfrr currently doesn't load any config, and has some hardcoded
     514             :          * settings that show up in "show run".  skip it here (for now at
     515             :          * least) so we don't get that mangled up in config-write.
     516             :          */
     517           0 :         if (head_client->flag == VTYSH_WATCHFRR)
     518             :                 return;
     519             : 
     520             :         /* suppress output to user */
     521           0 :         vty->of_saved = vty->of;
     522           0 :         vty->of = NULL;
     523           0 :         vtysh_client_run_all(head_client, line, 1, vtysh_config_parse_line,
     524             :                              NULL);
     525           0 :         vty->of = vty->of_saved;
     526             : }
     527             : 
     528             : /* Command execution over the vty interface. */
     529          12 : static int vtysh_execute_func(const char *line, int pager)
     530             : {
     531          12 :         int ret, cmd_stat;
     532          12 :         unsigned int i;
     533          12 :         vector vline;
     534          12 :         const struct cmd_element *cmd;
     535          12 :         int tried = 0;
     536          12 :         int saved_ret, saved_node;
     537             : 
     538             :         /* Split readline string up into the vector. */
     539          12 :         vline = cmd_make_strvec(line);
     540             : 
     541          12 :         if (vline == NULL)
     542             :                 return CMD_SUCCESS;
     543             : 
     544          12 :         if (vtysh_add_timestamp && strncmp(line, "exit", 4)) {
     545           0 :                 char ts[48];
     546             : 
     547           0 :                 (void)frr_timestamp(3, ts, sizeof(ts));
     548           0 :                 vty_out(vty, "%% %s\n\n", ts);
     549             :         }
     550             : 
     551          12 :         saved_ret = ret = cmd_execute(vty, line, &cmd, 1);
     552          12 :         saved_node = vty->node;
     553             : 
     554             :         /*
     555             :          * If command doesn't succeeded in current node, try to walk up in node
     556             :          * tree. Changing vty->node is enough to try it just out without actual
     557             :          * walkup in the vtysh.
     558             :          */
     559          12 :         while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON
     560           0 :                && ret != CMD_WARNING && ret != CMD_WARNING_CONFIG_FAILED
     561           0 :                && ret != CMD_ERR_AMBIGUOUS && ret != CMD_ERR_INCOMPLETE
     562          12 :                && vty->node > CONFIG_NODE) {
     563           0 :                 vty->node = node_parent(vty->node);
     564           0 :                 ret = cmd_execute(vty, line, &cmd, 1);
     565           0 :                 tried++;
     566             :         }
     567             : 
     568          12 :         vty->node = saved_node;
     569             : 
     570             :         /*
     571             :          * If command succeeded in any other node than current (tried > 0) we
     572             :          * have to move into node in the vtysh where it succeeded.
     573             :          */
     574          12 :         if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON
     575           0 :             || ret == CMD_WARNING) {
     576          12 :                 while (tried-- > 0)
     577          12 :                         vtysh_execute("exit");
     578             :         }
     579             :         /*
     580             :          * If command didn't succeed in any node, continue with return value
     581             :          * from first try.
     582             :          */
     583           0 :         else if (tried) {
     584          12 :                 ret = saved_ret;
     585             :         }
     586             : 
     587          12 :         cmd_free_strvec(vline);
     588             : 
     589          12 :         cmd_stat = ret;
     590          12 :         switch (ret) {
     591           0 :         case CMD_WARNING:
     592             :         case CMD_WARNING_CONFIG_FAILED:
     593           0 :                 if (vty->type == VTY_FILE)
     594           0 :                         vty_out(vty, "Warning...\n");
     595             :                 break;
     596           0 :         case CMD_ERR_AMBIGUOUS:
     597           0 :                 vty_out(vty, "%% Ambiguous command: %s\n", line);
     598           0 :                 break;
     599           0 :         case CMD_ERR_NO_MATCH:
     600           0 :                 vty_out(vty, "%% Unknown command: %s\n", line);
     601           0 :                 break;
     602           0 :         case CMD_ERR_INCOMPLETE:
     603           0 :                 vty_out(vty, "%% Command incomplete: %s\n", line);
     604           0 :                 break;
     605           8 :         case CMD_SUCCESS_DAEMON: {
     606             :                 /*
     607             :                  * FIXME: Don't open pager for exit commands. popen() causes
     608             :                  * problems if exited from vtysh at all. This hack shouldn't
     609             :                  * cause any problem but is really ugly.
     610             :                  */
     611           8 :                 if (pager && strncmp(line, "exit", 4))
     612           0 :                         vty_open_pager(vty);
     613             : 
     614           8 :                 if (!strcmp(cmd->string, "configure")) {
     615           0 :                         for (i = 0; i < array_size(vtysh_client); i++) {
     616           0 :                                 cmd_stat = vtysh_client_execute(
     617             :                                         &vtysh_client[i], line);
     618           0 :                                 if (cmd_stat == CMD_WARNING)
     619             :                                         break;
     620             :                         }
     621             : 
     622           0 :                         if (cmd_stat) {
     623           0 :                                 line = "end";
     624           0 :                                 vline = cmd_make_strvec(line);
     625             : 
     626             : 
     627           0 :                                 if (vline == NULL) {
     628           0 :                                         if (vty->is_paged)
     629           0 :                                                 vty_close_pager(vty);
     630           0 :                                         return CMD_SUCCESS;
     631             :                                 }
     632             : 
     633           0 :                                 ret = cmd_execute_command(vline, vty, &cmd, 1);
     634           0 :                                 cmd_free_strvec(vline);
     635           0 :                                 if (ret != CMD_SUCCESS_DAEMON)
     636             :                                         break;
     637           0 :                         } else if (cmd->func) {
     638           0 :                                 (*cmd->func)(cmd, vty, 0, NULL);
     639           0 :                                 break;
     640             :                         }
     641             :                 }
     642             : 
     643           8 :                 cmd_stat = CMD_SUCCESS;
     644           8 :                 struct vtysh_client *vc;
     645         176 :                 for (i = 0; i < array_size(vtysh_client); i++) {
     646         168 :                         if (cmd->daemon & vtysh_client[i].flag) {
     647         168 :                                 if (vtysh_client[i].fd < 0
     648         164 :                                     && (cmd->daemon == vtysh_client[i].flag)) {
     649           0 :                                         for (vc = &vtysh_client[i]; vc;
     650           0 :                                              vc = vc->next)
     651           0 :                                                 if (vc->fd == VTYSH_WAS_ACTIVE)
     652           0 :                                                         vtysh_reconnect(vc);
     653             :                                 }
     654         168 :                                 if (vtysh_client[i].fd < 0
     655         164 :                                     && (cmd->daemon == vtysh_client[i].flag)) {
     656           0 :                                         bool any_inst = false;
     657           0 :                                         for (vc = &vtysh_client[i]; vc;
     658           0 :                                              vc = vc->next)
     659           0 :                                                 any_inst = any_inst
     660           0 :                                                            || (vc->fd > 0);
     661           0 :                                         if (!any_inst) {
     662           0 :                                                 fprintf(stderr,
     663             :                                                         "%s is not running\n",
     664             :                                                         vtysh_client[i].name);
     665           0 :                                                 cmd_stat = CMD_ERR_NO_DAEMON;
     666           0 :                                                 break;
     667             :                                         }
     668             :                                 }
     669         168 :                                 cmd_stat = vtysh_client_execute(
     670             :                                         &vtysh_client[i], line);
     671         168 :                                 if (cmd_stat != CMD_SUCCESS)
     672             :                                         break;
     673             :                         }
     674             :                 }
     675           8 :                 if (cmd_stat != CMD_SUCCESS && cmd_stat != CMD_ERR_NO_DAEMON)
     676             :                         break;
     677             : 
     678           8 :                 if (cmd->func)
     679           8 :                         (*cmd->func)(cmd, vty, 0, NULL);
     680             :         }
     681             :         }
     682          12 :         if (vty->is_paged)
     683           0 :                 vty_close_pager(vty);
     684             : 
     685             :         return cmd_stat;
     686             : }
     687             : 
     688          12 : int vtysh_execute_no_pager(const char *line)
     689             : {
     690          12 :         return vtysh_execute_func(line, 0);
     691             : }
     692             : 
     693           0 : int vtysh_execute(const char *line)
     694             : {
     695           0 :         return vtysh_execute_func(line, 1);
     696             : }
     697             : 
     698           9 : static char *trim(char *s)
     699             : {
     700           9 :         size_t size;
     701           9 :         char *end;
     702             : 
     703           9 :         size = strlen(s);
     704             : 
     705           9 :         if (!size)
     706             :                 return s;
     707             : 
     708           9 :         end = s + size - 1;
     709          17 :         while (end >= s && isspace((unsigned char)*end))
     710           8 :                 end--;
     711           9 :         *(end + 1) = '\0';
     712             : 
     713           9 :         while (*s && isspace((unsigned char)*s))
     714           0 :                 s++;
     715             : 
     716             :         return s;
     717             : }
     718             : 
     719           0 : int vtysh_mark_file(const char *filename)
     720             : {
     721           0 :         struct vty *vty;
     722           0 :         FILE *confp = NULL;
     723           0 :         int ret;
     724           0 :         vector vline;
     725           0 :         int tried = 0;
     726           0 :         const struct cmd_element *cmd;
     727           0 :         int saved_ret, prev_node;
     728           0 :         int lineno = 0;
     729           0 :         char *vty_buf_copy = NULL;
     730           0 :         char *vty_buf_trimmed = NULL;
     731             : 
     732           0 :         if (strncmp("-", filename, 1) == 0)
     733           0 :                 confp = stdin;
     734             :         else
     735           0 :                 confp = fopen(filename, "r");
     736             : 
     737           0 :         if (confp == NULL) {
     738           0 :                 fprintf(stderr, "%% Can't open config file %s due to '%s'.\n",
     739           0 :                         filename, safe_strerror(errno));
     740           0 :                 return CMD_ERR_NO_FILE;
     741             :         }
     742             : 
     743           0 :         vty = vty_new();
     744           0 :         vty->wfd = STDOUT_FILENO;
     745           0 :         vty->type = VTY_TERM;
     746           0 :         vty->node = CONFIG_NODE;
     747             : 
     748           0 :         vtysh_execute_no_pager("enable");
     749           0 :         vtysh_execute_no_pager("configure");
     750           0 :         vty_buf_copy = XCALLOC(MTYPE_VTYSH_CMD, VTY_BUFSIZ);
     751             : 
     752           0 :         while (fgets(vty->buf, VTY_BUFSIZ, confp)) {
     753           0 :                 lineno++;
     754           0 :                 tried = 0;
     755           0 :                 strlcpy(vty_buf_copy, vty->buf, VTY_BUFSIZ);
     756           0 :                 vty_buf_trimmed = trim(vty_buf_copy);
     757             : 
     758           0 :                 if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') {
     759           0 :                         vty_out(vty, "%s", vty->buf);
     760           0 :                         continue;
     761             :                 }
     762             : 
     763             :                 /* Split readline string up into the vector. */
     764           0 :                 vline = cmd_make_strvec(vty->buf);
     765             : 
     766           0 :                 if (vline == NULL) {
     767           0 :                         vty_out(vty, "%s", vty->buf);
     768           0 :                         continue;
     769             :                 }
     770             : 
     771             :                 /*
     772             :                  * Ignore the "end" lines, we will generate these where
     773             :                  * appropriate
     774             :                  */
     775           0 :                 if (strlen(vty_buf_trimmed) == 3
     776           0 :                     && strncmp("end", vty_buf_trimmed, 3) == 0) {
     777           0 :                         cmd_free_strvec(vline);
     778           0 :                         continue;
     779             :                 }
     780             : 
     781           0 :                 prev_node = vty->node;
     782           0 :                 saved_ret = ret = cmd_execute_command_strict(vline, vty, &cmd);
     783             : 
     784             :                 /*
     785             :                  * If command doesn't succeeded in current node, try to walk up
     786             :                  * in node tree. Changing vty->node is enough to try it just
     787             :                  * out without actual walkup in the vtysh.
     788             :                  */
     789           0 :                 while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON
     790           0 :                        && ret != CMD_WARNING && ret != CMD_WARNING_CONFIG_FAILED
     791           0 :                        && ret != CMD_ERR_AMBIGUOUS && ret != CMD_ERR_INCOMPLETE
     792           0 :                        && vty->node > CONFIG_NODE) {
     793           0 :                         vty->node = node_parent(vty->node);
     794           0 :                         ret = cmd_execute_command_strict(vline, vty, &cmd);
     795           0 :                         tried++;
     796             :                 }
     797             : 
     798             :                 /*
     799             :                  * If command succeeded in any other node than current (tried >
     800             :                  * 0) we have to move into node in the vtysh where it
     801             :                  * succeeded.
     802             :                  */
     803           0 :                 if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON
     804           0 :                     || ret == CMD_WARNING) {
     805           0 :                         while (tried-- > 0)
     806           0 :                                 vty_out(vty, "exit\n");
     807             :                 }
     808             :                 /*
     809             :                  * If command didn't succeed in any node, continue with return
     810             :                  * value from first try.
     811             :                  */
     812           0 :                 else if (tried) {
     813           0 :                         ret = saved_ret;
     814           0 :                         vty->node = prev_node;
     815             :                 }
     816             : 
     817           0 :                 cmd_free_strvec(vline);
     818           0 :                 switch (ret) {
     819           0 :                 case CMD_WARNING:
     820             :                 case CMD_WARNING_CONFIG_FAILED:
     821           0 :                         if (vty->type == VTY_FILE)
     822           0 :                                 fprintf(stderr, "line %d: Warning...: %s\n",
     823             :                                         lineno, vty->buf);
     824           0 :                         fclose(confp);
     825           0 :                         vty_close(vty);
     826           0 :                         XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
     827           0 :                         return ret;
     828           0 :                 case CMD_ERR_AMBIGUOUS:
     829           0 :                         fprintf(stderr, "line %d: %% Ambiguous command: %s\n",
     830             :                                 lineno, vty->buf);
     831           0 :                         fclose(confp);
     832           0 :                         vty_close(vty);
     833           0 :                         XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
     834           0 :                         return CMD_ERR_AMBIGUOUS;
     835           0 :                 case CMD_ERR_NO_MATCH:
     836           0 :                         fprintf(stderr, "line %d: %% Unknown command: %s\n",
     837             :                                 lineno, vty->buf);
     838           0 :                         fclose(confp);
     839           0 :                         vty_close(vty);
     840           0 :                         XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
     841           0 :                         return CMD_ERR_NO_MATCH;
     842           0 :                 case CMD_ERR_INCOMPLETE:
     843           0 :                         fprintf(stderr, "line %d: %% Command incomplete: %s\n",
     844             :                                 lineno, vty->buf);
     845           0 :                         fclose(confp);
     846           0 :                         vty_close(vty);
     847           0 :                         XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
     848           0 :                         return CMD_ERR_INCOMPLETE;
     849           0 :                 case CMD_SUCCESS:
     850           0 :                         vty_out(vty, "%s", vty->buf);
     851           0 :                         if (strmatch(vty_buf_trimmed, "exit-vrf"))
     852           0 :                                 vty_out(vty, "end\n");
     853             :                         break;
     854           0 :                 case CMD_SUCCESS_DAEMON: {
     855           0 :                         int cmd_stat;
     856             : 
     857           0 :                         vty_out(vty, "%s", vty->buf);
     858           0 :                         if (strmatch(vty_buf_trimmed, "exit-vrf"))
     859           0 :                                 vty_out(vty, "end\n");
     860           0 :                         cmd_stat = vtysh_client_execute(&vtysh_client[0],
     861           0 :                                                         vty->buf);
     862           0 :                         if (cmd_stat != CMD_SUCCESS)
     863             :                                 break;
     864             : 
     865           0 :                         if (cmd->func)
     866           0 :                                 (*cmd->func)(cmd, vty, 0, NULL);
     867             :                 }
     868             :                 }
     869             :         }
     870             :         /* This is the end */
     871           0 :         vty_out(vty, "\nend\n");
     872           0 :         vty_close(vty);
     873           0 :         XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
     874             : 
     875           0 :         if (confp != stdin)
     876           0 :                 fclose(confp);
     877             : 
     878             :         return 0;
     879             : }
     880             : 
     881             : /* Configuration make from file. */
     882           2 : int vtysh_config_from_file(struct vty *vty, FILE *fp)
     883             : {
     884           2 :         int ret;
     885           2 :         const struct cmd_element *cmd;
     886           2 :         int lineno = 0;
     887             :         /* once we have an error, we remember & return that */
     888           2 :         int retcode = CMD_SUCCESS;
     889           2 :         char *vty_buf_copy = XCALLOC(MTYPE_VTYSH_CMD, VTY_BUFSIZ);
     890           2 :         char *vty_buf_trimmed = NULL;
     891             : 
     892          11 :         while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
     893           9 :                 lineno++;
     894             : 
     895           9 :                 strlcpy(vty_buf_copy, vty->buf, VTY_BUFSIZ);
     896           9 :                 vty_buf_trimmed = trim(vty_buf_copy);
     897             : 
     898             :                 /*
     899             :                  * Ignore the "end" lines, we will generate these where
     900             :                  * appropriate, otherwise we never execute
     901             :                  * XFRR_end_configuration, and start/end markers do not work.
     902             :                  */
     903           9 :                 if (strmatch(vty_buf_trimmed, "end"))
     904           0 :                         continue;
     905             : 
     906           9 :                 ret = command_config_read_one_line(vty, &cmd, lineno, 1);
     907             : 
     908           9 :                 switch (ret) {
     909           0 :                 case CMD_WARNING:
     910             :                 case CMD_WARNING_CONFIG_FAILED:
     911           0 :                         if (vty->type == VTY_FILE)
     912           0 :                                 fprintf(stderr, "line %d: Warning[%d]...: %s\n",
     913             :                                         lineno, vty->node, vty->buf);
     914             :                         retcode = ret;
     915             : 
     916             :                         break;
     917           0 :                 case CMD_ERR_AMBIGUOUS:
     918           0 :                         fprintf(stderr,
     919             :                                 "line %d: %% Ambiguous command[%d]: %s\n",
     920             :                                 lineno, vty->node, vty->buf);
     921           0 :                         retcode = CMD_ERR_AMBIGUOUS;
     922           0 :                         break;
     923           0 :                 case CMD_ERR_NO_MATCH:
     924           0 :                         fprintf(stderr, "line %d: %% Unknown command[%d]: %s",
     925             :                                 lineno, vty->node, vty->buf);
     926           0 :                         retcode = CMD_ERR_NO_MATCH;
     927           0 :                         break;
     928           0 :                 case CMD_ERR_INCOMPLETE:
     929           0 :                         fprintf(stderr,
     930             :                                 "line %d: %% Command incomplete[%d]: %s\n",
     931             :                                 lineno, vty->node, vty->buf);
     932           0 :                         retcode = CMD_ERR_INCOMPLETE;
     933           0 :                         break;
     934             :                 case CMD_SUCCESS_DAEMON: {
     935             :                         unsigned int i;
     936             :                         int cmd_stat = CMD_SUCCESS;
     937             : 
     938          88 :                         for (i = 0; i < array_size(vtysh_client); i++) {
     939          84 :                                 if (cmd->daemon & vtysh_client[i].flag) {
     940         160 :                                         cmd_stat = vtysh_client_execute(
     941          80 :                                                 &vtysh_client[i], vty->buf);
     942             :                                         /*
     943             :                                          * CMD_WARNING - Can mean that the
     944             :                                          * command was parsed successfully but
     945             :                                          * it was already entered in a few
     946             :                                          * spots. As such if we receive a
     947             :                                          * CMD_WARNING from a daemon we
     948             :                                          * shouldn't stop talking to the other
     949             :                                          * daemons for the particular command.
     950             :                                          */
     951          80 :                                         if (cmd_stat != CMD_SUCCESS
     952          80 :                                             && cmd_stat != CMD_WARNING) {
     953           0 :                                                 fprintf(stderr,
     954             :                                                         "line %d: Failure to communicate[%d] to %s, line: %s\n",
     955             :                                                         lineno, cmd_stat,
     956             :                                                         vtysh_client[i].name,
     957             :                                                         vty->buf);
     958           0 :                                                 retcode = cmd_stat;
     959           0 :                                                 break;
     960             :                                         }
     961             :                                 }
     962             :                         }
     963           4 :                         if (cmd_stat != CMD_SUCCESS)
     964             :                                 break;
     965             : 
     966           4 :                         if (cmd->func)
     967           1 :                                 (*cmd->func)(cmd, vty, 0, NULL);
     968             :                 }
     969             :                 }
     970             :         }
     971             : 
     972           2 :         XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
     973             : 
     974           2 :         return (retcode);
     975             : }
     976             : 
     977             : /*
     978             :  * Function processes cli commands terminated with '?' character when entered
     979             :  * through either 'vtysh' or 'vtysh -c' interfaces.
     980             :  */
     981           0 : static int vtysh_process_questionmark(const char *input, int input_len)
     982             : {
     983           0 :         int ret, width = 0;
     984           0 :         unsigned int i;
     985           0 :         vector vline, describe;
     986           0 :         struct cmd_token *token;
     987             : 
     988           0 :         if (!input)
     989             :                 return 1;
     990             : 
     991           0 :         vline = cmd_make_strvec(input);
     992             : 
     993             :         /* In case of '> ?'. */
     994           0 :         if (vline == NULL) {
     995           0 :                 vline = vector_init(1);
     996           0 :                 vector_set(vline, NULL);
     997           0 :         } else if (input_len && isspace((unsigned char)input[input_len - 1]))
     998           0 :                 vector_set(vline, NULL);
     999             : 
    1000           0 :         describe = cmd_describe_command(vline, vty, &ret);
    1001             : 
    1002             :         /* Ambiguous and no match error. */
    1003           0 :         switch (ret) {
    1004           0 :         case CMD_ERR_AMBIGUOUS:
    1005           0 :                 cmd_free_strvec(vline);
    1006           0 :                 vector_free(describe);
    1007           0 :                 vty_out(vty, "%% Ambiguous command.\n");
    1008           0 :                 rl_on_new_line();
    1009           0 :                 return 0;
    1010           0 :         case CMD_ERR_NO_MATCH:
    1011           0 :                 cmd_free_strvec(vline);
    1012           0 :                 if (describe)
    1013           0 :                         vector_free(describe);
    1014           0 :                 vty_out(vty, "%% There is no matched command.\n");
    1015           0 :                 rl_on_new_line();
    1016           0 :                 return 0;
    1017             :         }
    1018             : 
    1019             :         /* Get width of command string. */
    1020             :         width = 0;
    1021           0 :         for (i = 0; i < vector_active(describe); i++)
    1022           0 :                 if ((token = vector_slot(describe, i)) != NULL) {
    1023           0 :                         if (token->text[0] == '\0')
    1024           0 :                                 continue;
    1025             : 
    1026           0 :                         int len = strlen(token->text);
    1027             : 
    1028           0 :                         if (width < len)
    1029           0 :                                 width = len;
    1030             :                 }
    1031             : 
    1032           0 :         for (i = 0; i < vector_active(describe); i++)
    1033           0 :                 if ((token = vector_slot(describe, i)) != NULL) {
    1034           0 :                         if (!token->desc)
    1035           0 :                                 vty_out(vty, "  %-s\n", token->text);
    1036             :                         else
    1037           0 :                                 vty_out(vty, "  %-*s  %s\n", width, token->text,
    1038             :                                         token->desc);
    1039             : 
    1040           0 :                         if (IS_VARYING_TOKEN(token->type)) {
    1041           0 :                                 const char *ref = vector_slot(
    1042             :                                         vline, vector_active(vline) - 1);
    1043             : 
    1044           0 :                                 vector varcomps = vector_init(VECTOR_MIN_SIZE);
    1045           0 :                                 cmd_variable_complete(token, ref, varcomps);
    1046             : 
    1047           0 :                                 if (vector_active(varcomps) > 0) {
    1048           0 :                                         int rows, cols;
    1049           0 :                                         rl_get_screen_size(&rows, &cols);
    1050             : 
    1051           0 :                                         char *ac = cmd_variable_comp2str(
    1052             :                                                 varcomps, cols);
    1053           0 :                                         vty_out(vty, "%s\n", ac);
    1054           0 :                                         XFREE(MTYPE_TMP, ac);
    1055             :                                 }
    1056             : 
    1057           0 :                                 vector_free(varcomps);
    1058             :                         }
    1059             :                 }
    1060             : 
    1061           0 :         cmd_free_strvec(vline);
    1062           0 :         vector_free(describe);
    1063             : 
    1064           0 :         return 0;
    1065             : }
    1066             : 
    1067             : /*
    1068             :  * Entry point for user commands terminated with '?' character and typed through
    1069             :  * the usual vtysh's stdin interface. This is the function being registered with
    1070             :  * readline() api's.
    1071             :  */
    1072           0 : static int vtysh_rl_describe(int a, int b)
    1073             : {
    1074           0 :         int ret;
    1075             : 
    1076           0 :         vty_out(vty, "\n");
    1077             : 
    1078           0 :         ret = vtysh_process_questionmark(rl_line_buffer, rl_end);
    1079           0 :         rl_on_new_line();
    1080             : 
    1081           0 :         return ret;
    1082             : }
    1083             : 
    1084             : /*
    1085             :  * Function in charged of processing vtysh instructions terminating with '?'
    1086             :  * character and received through the 'vtysh -c' interface. If user's
    1087             :  * instruction is well-formatted, we will call the same processing routine
    1088             :  * utilized by the traditional vtysh's stdin interface.
    1089             :  */
    1090           0 : int vtysh_execute_command_questionmark(char *input)
    1091             : {
    1092           0 :         int input_len, qmark_count = 0;
    1093           0 :         const char *str;
    1094             : 
    1095           0 :         if (!(input && *input))
    1096             :                 return 1;
    1097             : 
    1098             :         /* Finding out question_mark count and strlen */
    1099           0 :         for (str = input; *str; ++str) {
    1100           0 :                 if (*str == '?')
    1101           0 :                         qmark_count++;
    1102             :         }
    1103           0 :         input_len = str - input;
    1104             : 
    1105             :         /*
    1106             :          * Verify that user's input terminates in '?' and that patterns such as
    1107             :          * 'cmd ? subcmd ?' are prevented.
    1108             :          */
    1109           0 :         if (qmark_count != 1 || input[input_len - 1] != '?')
    1110             :                 return 1;
    1111             : 
    1112             :         /*
    1113             :          * Questionmark-processing function is not expecting to receive '?'
    1114             :          * character in input string.
    1115             :          */
    1116           0 :         input[input_len - 1] = '\0';
    1117             : 
    1118           0 :         return vtysh_process_questionmark(input, input_len - 1);
    1119             : }
    1120             : 
    1121             : /* Result of cmd_complete_command() call will be stored here
    1122             :  * and used in new_completion() in order to put the space in
    1123             :  * correct places only. */
    1124             : int complete_status;
    1125             : 
    1126           0 : static char *command_generator(const char *text, int state)
    1127             : {
    1128           0 :         vector vline;
    1129           0 :         static char **matched = NULL;
    1130           0 :         static int index = 0;
    1131             : 
    1132             :         /* First call. */
    1133           0 :         if (!state) {
    1134           0 :                 index = 0;
    1135             : 
    1136           0 :                 if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
    1137             :                         return NULL;
    1138             : 
    1139           0 :                 vline = cmd_make_strvec(rl_line_buffer);
    1140           0 :                 if (vline == NULL)
    1141             :                         return NULL;
    1142             : 
    1143           0 :                 if (rl_end &&
    1144           0 :                     isspace((unsigned char)rl_line_buffer[rl_end - 1]))
    1145           0 :                         vector_set(vline, NULL);
    1146             : 
    1147           0 :                 matched = cmd_complete_command(vline, vty, &complete_status);
    1148           0 :                 cmd_free_strvec(vline);
    1149             :         }
    1150             : 
    1151           0 :         if (matched && matched[index]) {
    1152           0 :                 XCOUNTFREE(MTYPE_COMPLETION, matched[index]);
    1153           0 :                 return matched[index++];
    1154             :         }
    1155             : 
    1156           0 :         XFREE(MTYPE_TMP, matched);
    1157             : 
    1158           0 :         return NULL;
    1159             : }
    1160             : 
    1161           0 : static char **new_completion(const char *text, int start, int end)
    1162             : {
    1163           0 :         char **matches;
    1164             : 
    1165           0 :         matches = rl_completion_matches(text, command_generator);
    1166             : 
    1167           0 :         if (matches) {
    1168           0 :                 rl_point = rl_end;
    1169           0 :                 if (complete_status != CMD_COMPLETE_FULL_MATCH)
    1170             :                         /* only append a space on full match */
    1171           0 :                         rl_completion_append_character = '\0';
    1172             :         }
    1173             : 
    1174           0 :         return matches;
    1175             : }
    1176             : 
    1177             : /* Vty node structures. */
    1178             : #ifdef HAVE_BGPD
    1179             : static struct cmd_node bgp_node = {
    1180             :         .name = "bgp",
    1181             :         .node = BGP_NODE,
    1182             :         .parent_node = CONFIG_NODE,
    1183             :         .prompt = "%s(config-router)# ",
    1184             : };
    1185             : #endif /* HAVE_BGPD */
    1186             : 
    1187             : static struct cmd_node rip_node = {
    1188             :         .name = "rip",
    1189             :         .node = RIP_NODE,
    1190             :         .parent_node = CONFIG_NODE,
    1191             :         .prompt = "%s(config-router)# ",
    1192             : };
    1193             : 
    1194             : #ifdef HAVE_ISISD
    1195             : static struct cmd_node isis_node = {
    1196             :         .name = "isis",
    1197             :         .node = ISIS_NODE,
    1198             :         .parent_node = CONFIG_NODE,
    1199             :         .prompt = "%s(config-router)# ",
    1200             : };
    1201             : #endif /* HAVE_ISISD */
    1202             : 
    1203             : #ifdef HAVE_FABRICD
    1204             : static struct cmd_node openfabric_node = {
    1205             :         .name = "openfabric",
    1206             :         .node = OPENFABRIC_NODE,
    1207             :         .parent_node = CONFIG_NODE,
    1208             :         .prompt = "%s(config-router)# ",
    1209             : };
    1210             : #endif /* HAVE_FABRICD */
    1211             : 
    1212             : static struct cmd_node interface_node = {
    1213             :         .name = "interface",
    1214             :         .node = INTERFACE_NODE,
    1215             :         .parent_node = CONFIG_NODE,
    1216             :         .prompt = "%s(config-if)# ",
    1217             : };
    1218             : 
    1219             : static struct cmd_node pw_node = {
    1220             :         .name = "pw",
    1221             :         .node = PW_NODE,
    1222             :         .parent_node = CONFIG_NODE,
    1223             :         .prompt = "%s(config-pw)# ",
    1224             : };
    1225             : 
    1226             : static struct cmd_node segment_routing_node = {
    1227             :         .name = "segment-routing",
    1228             :         .node = SEGMENT_ROUTING_NODE,
    1229             :         .parent_node = CONFIG_NODE,
    1230             :         .prompt = "%s(config-sr)# ",
    1231             : };
    1232             : 
    1233             : #if defined(HAVE_PATHD)
    1234             : static struct cmd_node sr_traffic_eng_node = {
    1235             :         .name = "sr traffic-eng",
    1236             :         .node = SR_TRAFFIC_ENG_NODE,
    1237             :         .parent_node = SEGMENT_ROUTING_NODE,
    1238             :         .prompt = "%s(config-sr-te)# ",
    1239             : };
    1240             : 
    1241             : static struct cmd_node srte_segment_list_node = {
    1242             :         .name = "srte segment-list",
    1243             :         .node = SR_SEGMENT_LIST_NODE,
    1244             :         .parent_node = SR_TRAFFIC_ENG_NODE,
    1245             :         .prompt = "%s(config-sr-te-segment-list)# ",
    1246             : };
    1247             : 
    1248             : static struct cmd_node srte_policy_node = {
    1249             :         .name = "srte policy",
    1250             :         .node = SR_POLICY_NODE,
    1251             :         .parent_node = SR_TRAFFIC_ENG_NODE,
    1252             :         .prompt = "%s(config-sr-te-policy)# ",
    1253             : };
    1254             : 
    1255             : static struct cmd_node srte_candidate_dyn_node = {
    1256             :         .name = "srte candidate-dyn",
    1257             :         .node = SR_CANDIDATE_DYN_NODE,
    1258             :         .parent_node = SR_POLICY_NODE,
    1259             :         .prompt = "%s(config-sr-te-candidate)# ",
    1260             : };
    1261             : 
    1262             : static struct cmd_node pcep_node = {
    1263             :         .name = "srte pcep",
    1264             :         .node = PCEP_NODE,
    1265             :         .parent_node = SR_TRAFFIC_ENG_NODE,
    1266             :         .prompt = "%s(config-sr-te-pcep)# "
    1267             : };
    1268             : 
    1269             : static struct cmd_node pcep_pcc_node = {
    1270             :         .name = "srte pcep pcc",
    1271             :         .node = PCEP_PCC_NODE,
    1272             :         .parent_node = PCEP_NODE,
    1273             :         .prompt = "%s(config-sr-te-pcep-pcc)# ",
    1274             : };
    1275             : 
    1276             : static struct cmd_node pcep_pce_node = {
    1277             :         .name = "srte pcep pce-peer",
    1278             :         .node = PCEP_PCE_NODE,
    1279             :         .parent_node = PCEP_NODE,
    1280             :         .prompt = "%s(config-sr-te-pcep-pce-peer)# ",
    1281             : };
    1282             : 
    1283             : static struct cmd_node pcep_pce_config_node = {
    1284             :         .name = "srte pcep pce-config",
    1285             :         .node = PCEP_PCE_CONFIG_NODE,
    1286             :         .parent_node = PCEP_NODE,
    1287             :         .prompt = "%s(pcep-sr-te-pcep-pce-config)# ",
    1288             : };
    1289             : #endif /* HAVE_PATHD */
    1290             : 
    1291             : static struct cmd_node vrf_node = {
    1292             :         .name = "vrf",
    1293             :         .node = VRF_NODE,
    1294             :         .parent_node = CONFIG_NODE,
    1295             :         .prompt = "%s(config-vrf)# ",
    1296             : };
    1297             : 
    1298             : static struct cmd_node nh_group_node = {
    1299             :         .name = "nexthop-group",
    1300             :         .node = NH_GROUP_NODE,
    1301             :         .parent_node = CONFIG_NODE,
    1302             :         .prompt = "%s(config-nh-group)# ",
    1303             : };
    1304             : 
    1305             : static struct cmd_node rmap_node = {
    1306             :         .name = "routemap",
    1307             :         .node = RMAP_NODE,
    1308             :         .parent_node = CONFIG_NODE,
    1309             :         .prompt = "%s(config-route-map)# ",
    1310             : };
    1311             : 
    1312             : static struct cmd_node srv6_node = {
    1313             :         .name = "srv6",
    1314             :         .node = SRV6_NODE,
    1315             :         .parent_node = SEGMENT_ROUTING_NODE,
    1316             :         .prompt = "%s(config-srv6)# ",
    1317             : };
    1318             : 
    1319             : static struct cmd_node srv6_locs_node = {
    1320             :         .name = "srv6-locators",
    1321             :         .node = SRV6_LOCS_NODE,
    1322             :         .parent_node = SRV6_NODE,
    1323             :         .prompt = "%s(config-srv6-locators)# ",
    1324             : };
    1325             : 
    1326             : static struct cmd_node srv6_loc_node = {
    1327             :         .name = "srv6-locator",
    1328             :         .node = SRV6_LOC_NODE,
    1329             :         .parent_node = SRV6_LOCS_NODE,
    1330             :         .prompt = "%s(config-srv6-locator)# ",
    1331             : };
    1332             : 
    1333             : #ifdef HAVE_PBRD
    1334             : static struct cmd_node pbr_map_node = {
    1335             :         .name = "pbr-map",
    1336             :         .node = PBRMAP_NODE,
    1337             :         .parent_node = CONFIG_NODE,
    1338             :         .prompt = "%s(config-pbr-map)# ",
    1339             : };
    1340             : #endif /* HAVE_PBRD */
    1341             : 
    1342             : static struct cmd_node zebra_node = {
    1343             :         .name = "zebra",
    1344             :         .node = ZEBRA_NODE,
    1345             :         .parent_node = CONFIG_NODE,
    1346             :         .prompt = "%s(config-router)# ",
    1347             : };
    1348             : 
    1349             : #ifdef HAVE_BGPD
    1350             : static struct cmd_node bgp_vpnv4_node = {
    1351             :         .name = "bgp vpnv4",
    1352             :         .node = BGP_VPNV4_NODE,
    1353             :         .parent_node = BGP_NODE,
    1354             :         .prompt = "%s(config-router-af)# ",
    1355             :         .no_xpath = true,
    1356             : };
    1357             : 
    1358             : static struct cmd_node bgp_vpnv6_node = {
    1359             :         .name = "bgp vpnv6",
    1360             :         .node = BGP_VPNV6_NODE,
    1361             :         .parent_node = BGP_NODE,
    1362             :         .prompt = "%s(config-router-af)# ",
    1363             :         .no_xpath = true,
    1364             : };
    1365             : 
    1366             : static struct cmd_node bgp_flowspecv4_node = {
    1367             :         .name = "bgp ipv4 flowspec",
    1368             :         .node = BGP_FLOWSPECV4_NODE,
    1369             :         .parent_node = BGP_NODE,
    1370             :         .prompt = "%s(config-router-af)# ",
    1371             :         .no_xpath = true,
    1372             : };
    1373             : 
    1374             : static struct cmd_node bgp_flowspecv6_node = {
    1375             :         .name = "bgp ipv6 flowspec",
    1376             :         .node = BGP_FLOWSPECV6_NODE,
    1377             :         .parent_node = BGP_NODE,
    1378             :         .prompt = "%s(config-router-af)# ",
    1379             :         .no_xpath = true,
    1380             : };
    1381             : 
    1382             : static struct cmd_node bgp_ipv4_node = {
    1383             :         .name = "bgp ipv4 unicast",
    1384             :         .node = BGP_IPV4_NODE,
    1385             :         .parent_node = BGP_NODE,
    1386             :         .prompt = "%s(config-router-af)# ",
    1387             :         .no_xpath = true,
    1388             : };
    1389             : 
    1390             : static struct cmd_node bgp_ipv4m_node = {
    1391             :         .name = "bgp ipv4 multicast",
    1392             :         .node = BGP_IPV4M_NODE,
    1393             :         .parent_node = BGP_NODE,
    1394             :         .prompt = "%s(config-router-af)# ",
    1395             :         .no_xpath = true,
    1396             : };
    1397             : 
    1398             : static struct cmd_node bgp_ipv4l_node = {
    1399             :         .name = "bgp ipv4 labeled unicast",
    1400             :         .node = BGP_IPV4L_NODE,
    1401             :         .parent_node = BGP_NODE,
    1402             :         .prompt = "%s(config-router-af)# ",
    1403             :         .no_xpath = true,
    1404             : };
    1405             : 
    1406             : static struct cmd_node bgp_ipv6_node = {
    1407             :         .name = "bgp ipv6",
    1408             :         .node = BGP_IPV6_NODE,
    1409             :         .parent_node = BGP_NODE,
    1410             :         .prompt = "%s(config-router-af)# ",
    1411             :         .no_xpath = true,
    1412             : };
    1413             : 
    1414             : static struct cmd_node bgp_ipv6m_node = {
    1415             :         .name = "bgp ipv6 multicast",
    1416             :         .node = BGP_IPV6M_NODE,
    1417             :         .parent_node = BGP_NODE,
    1418             :         .prompt = "%s(config-router-af)# ",
    1419             :         .no_xpath = true,
    1420             : };
    1421             : 
    1422             : static struct cmd_node bgp_evpn_node = {
    1423             :         .name = "bgp evpn",
    1424             :         .node = BGP_EVPN_NODE,
    1425             :         .parent_node = BGP_NODE,
    1426             :         .prompt = "%s(config-router-af)# ",
    1427             :         .no_xpath = true,
    1428             : };
    1429             : 
    1430             : static struct cmd_node bgp_evpn_vni_node = {
    1431             :         .name = "bgp evpn vni",
    1432             :         .node = BGP_EVPN_VNI_NODE,
    1433             :         .parent_node = BGP_EVPN_NODE,
    1434             :         .prompt = "%s(config-router-af-vni)# ",
    1435             : };
    1436             : 
    1437             : static struct cmd_node bgp_ipv6l_node = {
    1438             :         .name = "bgp ipv6 labeled unicast",
    1439             :         .node = BGP_IPV6L_NODE,
    1440             :         .parent_node = BGP_NODE,
    1441             :         .prompt = "%s(config-router-af)# ",
    1442             :         .no_xpath = true,
    1443             : };
    1444             : 
    1445             : #ifdef ENABLE_BGP_VNC
    1446             : static struct cmd_node bgp_vnc_defaults_node = {
    1447             :         .name = "bgp vnc defaults",
    1448             :         .node = BGP_VNC_DEFAULTS_NODE,
    1449             :         .parent_node = BGP_NODE,
    1450             :         .prompt = "%s(config-router-vnc-defaults)# ",
    1451             : };
    1452             : 
    1453             : static struct cmd_node bgp_vnc_nve_group_node = {
    1454             :         .name = "bgp vnc nve",
    1455             :         .node = BGP_VNC_NVE_GROUP_NODE,
    1456             :         .parent_node = BGP_NODE,
    1457             :         .prompt = "%s(config-router-vnc-nve-group)# ",
    1458             : };
    1459             : 
    1460             : static struct cmd_node bgp_vrf_policy_node = {
    1461             :         .name = "bgp vrf policy",
    1462             :         .node = BGP_VRF_POLICY_NODE,
    1463             :         .parent_node = BGP_NODE,
    1464             :         .prompt = "%s(config-router-vrf-policy)# ",
    1465             : };
    1466             : 
    1467             : static struct cmd_node bgp_vnc_l2_group_node = {
    1468             :         .name = "bgp vnc l2",
    1469             :         .node = BGP_VNC_L2_GROUP_NODE,
    1470             :         .parent_node = BGP_NODE,
    1471             :         .prompt = "%s(config-router-vnc-l2-group)# ",
    1472             : };
    1473             : #endif /* ENABLE_BGP_VNC */
    1474             : 
    1475             : static struct cmd_node bmp_node = {
    1476             :         .name = "bmp",
    1477             :         .node = BMP_NODE,
    1478             :         .parent_node = BGP_NODE,
    1479             :         .prompt = "%s(config-bgp-bmp)# "
    1480             : };
    1481             : 
    1482             : static struct cmd_node bgp_srv6_node = {
    1483             :         .name = "bgp srv6",
    1484             :         .node = BGP_SRV6_NODE,
    1485             :         .parent_node = BGP_NODE,
    1486             :         .prompt = "%s(config-router-srv6)# ",
    1487             : };
    1488             : #endif /* HAVE_BGPD */
    1489             : 
    1490             : #ifdef HAVE_OSPFD
    1491             : static struct cmd_node ospf_node = {
    1492             :         .name = "ospf",
    1493             :         .node = OSPF_NODE,
    1494             :         .parent_node = CONFIG_NODE,
    1495             :         .prompt = "%s(config-router)# ",
    1496             : };
    1497             : #endif /* HAVE_OSPFD */
    1498             : 
    1499             : #ifdef HAVE_EIGRPD
    1500             : static struct cmd_node eigrp_node = {
    1501             :         .name = "eigrp",
    1502             :         .node = EIGRP_NODE,
    1503             :         .parent_node = CONFIG_NODE,
    1504             :         .prompt = "%s(config-router)# ",
    1505             : };
    1506             : #endif /* HAVE_EIGRPD */
    1507             : 
    1508             : #ifdef HAVE_BABELD
    1509             : static struct cmd_node babel_node = {
    1510             :         .name = "babel",
    1511             :         .node = BABEL_NODE,
    1512             :         .parent_node = CONFIG_NODE,
    1513             :         .prompt = "%s(config-router)# ",
    1514             : };
    1515             : #endif /* HAVE_BABELD */
    1516             : 
    1517             : static struct cmd_node ripng_node = {
    1518             :         .name = "ripng",
    1519             :         .node = RIPNG_NODE,
    1520             :         .parent_node = CONFIG_NODE,
    1521             :         .prompt = "%s(config-router)# ",
    1522             : };
    1523             : 
    1524             : #ifdef HAVE_OSPF6D
    1525             : static struct cmd_node ospf6_node = {
    1526             :         .name = "ospf6",
    1527             :         .node = OSPF6_NODE,
    1528             :         .parent_node = CONFIG_NODE,
    1529             :         .prompt = "%s(config-ospf6)# ",
    1530             : };
    1531             : #endif /* HAVE_OSPF6D */
    1532             : 
    1533             : #ifdef HAVE_LDPD
    1534             : static struct cmd_node ldp_node = {
    1535             :         .name = "ldp",
    1536             :         .node = LDP_NODE,
    1537             :         .parent_node = CONFIG_NODE,
    1538             :         .prompt = "%s(config-ldp)# ",
    1539             : };
    1540             : 
    1541             : static struct cmd_node ldp_ipv4_node = {
    1542             :         .name = "ldp ipv4",
    1543             :         .node = LDP_IPV4_NODE,
    1544             :         .parent_node = LDP_NODE,
    1545             :         .prompt = "%s(config-ldp-af)# ",
    1546             : };
    1547             : 
    1548             : static struct cmd_node ldp_ipv6_node = {
    1549             :         .name = "ldp ipv6",
    1550             :         .node = LDP_IPV6_NODE,
    1551             :         .parent_node = LDP_NODE,
    1552             :         .prompt = "%s(config-ldp-af)# ",
    1553             : };
    1554             : 
    1555             : static struct cmd_node ldp_ipv4_iface_node = {
    1556             :         .name = "ldp ipv4 interface",
    1557             :         .node = LDP_IPV4_IFACE_NODE,
    1558             :         .parent_node = LDP_IPV4_NODE,
    1559             :         .prompt = "%s(config-ldp-af-if)# ",
    1560             : };
    1561             : 
    1562             : static struct cmd_node ldp_ipv6_iface_node = {
    1563             :         .name = "ldp ipv6 interface",
    1564             :         .node = LDP_IPV6_IFACE_NODE,
    1565             :         .parent_node = LDP_IPV6_NODE,
    1566             :         .prompt = "%s(config-ldp-af-if)# ",
    1567             : };
    1568             : 
    1569             : static struct cmd_node ldp_l2vpn_node = {
    1570             :         .name = "ldp l2vpn",
    1571             :         .node = LDP_L2VPN_NODE,
    1572             :         .parent_node = CONFIG_NODE,
    1573             :         .prompt = "%s(config-l2vpn)# ",
    1574             : };
    1575             : 
    1576             : static struct cmd_node ldp_pseudowire_node = {
    1577             :         .name = "ldp",
    1578             :         .node = LDP_PSEUDOWIRE_NODE,
    1579             :         .parent_node = LDP_L2VPN_NODE,
    1580             :         .prompt = "%s(config-l2vpn-pw)# ",
    1581             : };
    1582             : #endif /* HAVE_LDPD */
    1583             : 
    1584             : static struct cmd_node keychain_node = {
    1585             :         .name = "keychain",
    1586             :         .node = KEYCHAIN_NODE,
    1587             :         .parent_node = CONFIG_NODE,
    1588             :         .prompt = "%s(config-keychain)# ",
    1589             : };
    1590             : 
    1591             : static struct cmd_node keychain_key_node = {
    1592             :         .name = "keychain key",
    1593             :         .node = KEYCHAIN_KEY_NODE,
    1594             :         .parent_node = KEYCHAIN_NODE,
    1595             :         .prompt = "%s(config-keychain-key)# ",
    1596             : };
    1597             : 
    1598             : struct cmd_node link_params_node = {
    1599             :         .name = "link-params",
    1600             :         .node = LINK_PARAMS_NODE,
    1601             :         .parent_node = INTERFACE_NODE,
    1602             :         .prompt = "%s(config-link-params)# ",
    1603             :         .no_xpath = true,
    1604             : };
    1605             : 
    1606             : #ifdef HAVE_BGPD
    1607             : static struct cmd_node rpki_node = {
    1608             :         .name = "rpki",
    1609             :         .node = RPKI_NODE,
    1610             :         .parent_node = CONFIG_NODE,
    1611             :         .prompt = "%s(config-rpki)# ",
    1612             : };
    1613             : #endif /* HAVE_BGPD */
    1614             : 
    1615             : #if HAVE_BFDD > 0
    1616             : static struct cmd_node bfd_node = {
    1617             :         .name = "bfd",
    1618             :         .node = BFD_NODE,
    1619             :         .parent_node = CONFIG_NODE,
    1620             :         .prompt = "%s(config-bfd)# ",
    1621             : };
    1622             : 
    1623             : static struct cmd_node bfd_peer_node = {
    1624             :         .name = "bfd peer",
    1625             :         .node = BFD_PEER_NODE,
    1626             :         .parent_node = BFD_NODE,
    1627             :         .prompt = "%s(config-bfd-peer)# ",
    1628             : };
    1629             : 
    1630             : static struct cmd_node bfd_profile_node = {
    1631             :         .name = "bfd profile",
    1632             :         .node = BFD_PROFILE_NODE,
    1633             :         .parent_node = BFD_NODE,
    1634             :         .prompt = "%s(config-bfd-profile)# ",
    1635             : };
    1636             : #endif /* HAVE_BFDD */
    1637             : 
    1638             : /* Defined in lib/vty.c */
    1639             : extern struct cmd_node vty_node;
    1640             : 
    1641             : /* When '^Z' is received from vty, move down to the enable mode. */
    1642           2 : static int vtysh_end(void)
    1643             : {
    1644           2 :         switch (vty->node) {
    1645             :         case VIEW_NODE:
    1646             :         case ENABLE_NODE:
    1647             :                 /* Nothing to do. */
    1648             :                 break;
    1649           2 :         default:
    1650           2 :                 vty->node = ENABLE_NODE;
    1651           2 :                 break;
    1652             :         }
    1653           2 :         return CMD_SUCCESS;
    1654             : }
    1655             : 
    1656             : #include "vtysh/vtysh_clippy.c"
    1657             : 
    1658           2 : DEFUNSH(VTYSH_REALLYALL, vtysh_end_all, vtysh_end_all_cmd, "end",
    1659             :         "End current mode and change to enable mode\n")
    1660             : {
    1661           2 :         return vtysh_end();
    1662             : }
    1663             : 
    1664           0 : DEFUNSH(VTYSH_ZEBRA, srv6, srv6_cmd,
    1665             :         "srv6",
    1666             :         "Segment-Routing SRv6 configuration\n")
    1667             : {
    1668           0 :         vty->node = SRV6_NODE;
    1669           0 :         return CMD_SUCCESS;
    1670             : }
    1671             : 
    1672           0 : DEFUNSH(VTYSH_ZEBRA, srv6_locators, srv6_locators_cmd,
    1673             :         "locators",
    1674             :         "Segment-Routing SRv6 locators configuration\n")
    1675             : {
    1676           0 :         vty->node = SRV6_LOCS_NODE;
    1677           0 :         return CMD_SUCCESS;
    1678             : }
    1679             : 
    1680           0 : DEFUNSH(VTYSH_ZEBRA, srv6_locator, srv6_locator_cmd,
    1681             :         "locator WORD",
    1682             :         "Segment Routing SRv6 locator\n"
    1683             :         "Specify locator-name\n")
    1684             : {
    1685           0 :         vty->node = SRV6_LOC_NODE;
    1686           0 :         return CMD_SUCCESS;
    1687             : }
    1688             : 
    1689             : #ifdef HAVE_BGPD
    1690           0 : DEFUNSH(VTYSH_BGPD, router_bgp, router_bgp_cmd,
    1691             :         "router bgp [(1-4294967295) [<view|vrf> VIEWVRFNAME]]",
    1692             :         ROUTER_STR BGP_STR AS_STR
    1693             :         "BGP view\nBGP VRF\n"
    1694             :         "View/VRF name\n")
    1695             : {
    1696           0 :         vty->node = BGP_NODE;
    1697           0 :         return CMD_SUCCESS;
    1698             : }
    1699             : 
    1700             : #ifdef KEEP_OLD_VPN_COMMANDS
    1701             : DEFUNSH(VTYSH_BGPD, address_family_vpnv4, address_family_vpnv4_cmd,
    1702             :         "address-family vpnv4 [unicast]",
    1703             :         "Enter Address Family command mode\n"
    1704             :         BGP_AF_STR
    1705             :         BGP_AF_MODIFIER_STR)
    1706             : {
    1707             :         vty->node = BGP_VPNV4_NODE;
    1708             :         return CMD_SUCCESS;
    1709             : }
    1710             : 
    1711             : DEFUNSH(VTYSH_BGPD, address_family_vpnv6, address_family_vpnv6_cmd,
    1712             :         "address-family vpnv6 [unicast]",
    1713             :         "Enter Address Family command mode\n"
    1714             :         BGP_AF_STR
    1715             :         BGP_AF_MODIFIER_STR)
    1716             : {
    1717             :         vty->node = BGP_VPNV6_NODE;
    1718             :         return CMD_SUCCESS;
    1719             : }
    1720             : #endif /* KEEP_OLD_VPN_COMMANDS */
    1721             : 
    1722           0 : DEFUNSH(VTYSH_BGPD, address_family_ipv4, address_family_ipv4_cmd,
    1723             :         "address-family ipv4 [unicast]",
    1724             :         "Enter Address Family command mode\n"
    1725             :         BGP_AF_STR
    1726             :         BGP_AF_MODIFIER_STR)
    1727             : {
    1728           0 :         vty->node = BGP_IPV4_NODE;
    1729           0 :         return CMD_SUCCESS;
    1730             : }
    1731             : 
    1732           0 : DEFUNSH(VTYSH_BGPD, address_family_flowspecv4, address_family_flowspecv4_cmd,
    1733             :         "address-family ipv4 flowspec",
    1734             :         "Enter Address Family command mode\n"
    1735             :         BGP_AF_STR
    1736             :         BGP_AF_MODIFIER_STR)
    1737             : {
    1738           0 :         vty->node = BGP_FLOWSPECV4_NODE;
    1739           0 :         return CMD_SUCCESS;
    1740             : }
    1741             : 
    1742           0 : DEFUNSH(VTYSH_BGPD, address_family_flowspecv6, address_family_flowspecv6_cmd,
    1743             :         "address-family ipv6 flowspec",
    1744             :         "Enter Address Family command mode\n"
    1745             :         BGP_AF_STR
    1746             :         BGP_AF_MODIFIER_STR)
    1747             : {
    1748           0 :         vty->node = BGP_FLOWSPECV6_NODE;
    1749           0 :         return CMD_SUCCESS;
    1750             : }
    1751             : 
    1752           0 : DEFUNSH(VTYSH_BGPD, address_family_ipv4_multicast,
    1753             :         address_family_ipv4_multicast_cmd, "address-family ipv4 multicast",
    1754             :         "Enter Address Family command mode\n"
    1755             :         BGP_AF_STR
    1756             :         BGP_AF_MODIFIER_STR)
    1757             : {
    1758           0 :         vty->node = BGP_IPV4M_NODE;
    1759           0 :         return CMD_SUCCESS;
    1760             : }
    1761             : 
    1762           0 : DEFUNSH(VTYSH_BGPD, address_family_ipv4_vpn, address_family_ipv4_vpn_cmd,
    1763             :         "address-family ipv4 vpn",
    1764             :         "Enter Address Family command mode\n"
    1765             :         BGP_AF_STR
    1766             :         BGP_AF_MODIFIER_STR)
    1767             : {
    1768           0 :         vty->node = BGP_VPNV4_NODE;
    1769           0 :         return CMD_SUCCESS;
    1770             : }
    1771             : 
    1772           0 : DEFUNSH(VTYSH_BGPD, address_family_ipv4_labeled_unicast,
    1773             :         address_family_ipv4_labeled_unicast_cmd,
    1774             :         "address-family ipv4 labeled-unicast",
    1775             :         "Enter Address Family command mode\n"
    1776             :         BGP_AF_STR
    1777             :         BGP_AF_MODIFIER_STR)
    1778             : {
    1779           0 :         vty->node = BGP_IPV4L_NODE;
    1780           0 :         return CMD_SUCCESS;
    1781             : }
    1782             : 
    1783           0 : DEFUNSH(VTYSH_BGPD, address_family_ipv6, address_family_ipv6_cmd,
    1784             :         "address-family ipv6 [unicast]",
    1785             :         "Enter Address Family command mode\n"
    1786             :         BGP_AF_STR
    1787             :         BGP_AF_MODIFIER_STR)
    1788             : {
    1789           0 :         vty->node = BGP_IPV6_NODE;
    1790           0 :         return CMD_SUCCESS;
    1791             : }
    1792             : 
    1793           0 : DEFUNSH(VTYSH_BGPD, address_family_ipv6_multicast,
    1794             :         address_family_ipv6_multicast_cmd, "address-family ipv6 multicast",
    1795             :         "Enter Address Family command mode\n"
    1796             :         BGP_AF_STR
    1797             :         BGP_AF_MODIFIER_STR)
    1798             : {
    1799           0 :         vty->node = BGP_IPV6M_NODE;
    1800           0 :         return CMD_SUCCESS;
    1801             : }
    1802             : 
    1803           0 : DEFUNSH(VTYSH_BGPD, address_family_ipv6_vpn, address_family_ipv6_vpn_cmd,
    1804             :         "address-family ipv6 vpn",
    1805             :         "Enter Address Family command mode\n"
    1806             :         BGP_AF_STR
    1807             :         BGP_AF_MODIFIER_STR)
    1808             : {
    1809           0 :         vty->node = BGP_VPNV6_NODE;
    1810           0 :         return CMD_SUCCESS;
    1811             : }
    1812             : 
    1813           0 : DEFUNSH(VTYSH_BGPD, address_family_ipv6_labeled_unicast,
    1814             :         address_family_ipv6_labeled_unicast_cmd,
    1815             :         "address-family ipv6 labeled-unicast",
    1816             :         "Enter Address Family command mode\n"
    1817             :         BGP_AF_STR
    1818             :         BGP_AF_MODIFIER_STR)
    1819             : {
    1820           0 :         vty->node = BGP_IPV6L_NODE;
    1821           0 :         return CMD_SUCCESS;
    1822             : }
    1823             : 
    1824           0 : DEFUNSH(VTYSH_BGPD,
    1825             :         rpki,
    1826             :         rpki_cmd,
    1827             :         "rpki",
    1828             :         "Enable rpki and enter rpki configuration mode\n")
    1829             : {
    1830           0 :         vty->node = RPKI_NODE;
    1831           0 :         return CMD_SUCCESS;
    1832             : }
    1833             : 
    1834           0 : DEFUNSH(VTYSH_BGPD,
    1835             :         bmp_targets,
    1836             :         bmp_targets_cmd,
    1837             :         "bmp targets BMPTARGETS",
    1838             :         "BGP Monitoring Protocol\n"
    1839             :         "Create BMP target group\n"
    1840             :         "Name of the BMP target group\n")
    1841             : {
    1842           0 :         vty->node = BMP_NODE;
    1843           0 :         return CMD_SUCCESS;
    1844             : }
    1845             : 
    1846           0 : DEFUNSH(VTYSH_BGPD,
    1847             :         bgp_srv6,
    1848             :         bgp_srv6_cmd,
    1849             :         "segment-routing srv6",
    1850             :         "Segment-Routing configuration\n"
    1851             :         "Segment-Routing SRv6 configuration\n")
    1852             : {
    1853           0 :         vty->node = BGP_SRV6_NODE;
    1854           0 :         return CMD_SUCCESS;
    1855             : }
    1856             : 
    1857           0 : DEFUNSH(VTYSH_BGPD,
    1858             :         exit_bgp_srv6,
    1859             :         exit_bgp_srv6_cmd,
    1860             :         "exit",
    1861             :         "exit Segment-Routing SRv6 configuration\n")
    1862             : {
    1863           0 :         if (vty->node == BGP_SRV6_NODE)
    1864           0 :                 vty->node = BGP_NODE;
    1865           0 :         return CMD_SUCCESS;
    1866             : }
    1867             : 
    1868           0 : DEFUNSH(VTYSH_BGPD,
    1869             :         quit_bgp_srv6,
    1870             :         quit_bgp_srv6_cmd,
    1871             :         "quit",
    1872             :         "quit Segment-Routing SRv6 configuration\n")
    1873             : {
    1874           0 :         if (vty->node == BGP_SRV6_NODE)
    1875           0 :                 vty->node = BGP_NODE;
    1876           0 :         return CMD_SUCCESS;
    1877             : }
    1878             : 
    1879           0 : DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
    1880             :         "address-family <l2vpn evpn>",
    1881             :         "Enter Address Family command mode\n"
    1882             :         BGP_AF_STR
    1883             :         BGP_AF_MODIFIER_STR)
    1884             : {
    1885           0 :         vty->node = BGP_EVPN_NODE;
    1886           0 :         return CMD_SUCCESS;
    1887             : }
    1888             : 
    1889           0 : DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni " CMD_VNI_RANGE,
    1890             :         "VXLAN Network Identifier\n"
    1891             :         "VNI number\n")
    1892             : {
    1893           0 :         vty->node = BGP_EVPN_VNI_NODE;
    1894           0 :         return CMD_SUCCESS;
    1895             : }
    1896             : 
    1897             : #if defined(ENABLE_BGP_VNC)
    1898           0 : DEFUNSH(VTYSH_BGPD, vnc_defaults, vnc_defaults_cmd, "vnc defaults",
    1899             :         "VNC/RFP related configuration\n"
    1900             :         "Configure default NVE group\n")
    1901             : {
    1902           0 :         vty->node = BGP_VNC_DEFAULTS_NODE;
    1903           0 :         return CMD_SUCCESS;
    1904             : }
    1905             : 
    1906           0 : DEFUNSH(VTYSH_BGPD, vnc_nve_group, vnc_nve_group_cmd, "vnc nve-group NAME",
    1907             :         "VNC/RFP related configuration\n"
    1908             :         "Configure a NVE group\n"
    1909             :         "Group name\n")
    1910             : {
    1911           0 :         vty->node = BGP_VNC_NVE_GROUP_NODE;
    1912           0 :         return CMD_SUCCESS;
    1913             : }
    1914             : 
    1915           0 : DEFUNSH(VTYSH_BGPD, vnc_vrf_policy, vnc_vrf_policy_cmd, "vrf-policy NAME",
    1916             :         "Configure a VRF policy group\n"
    1917             :         "Group name\n")
    1918             : {
    1919           0 :         vty->node = BGP_VRF_POLICY_NODE;
    1920           0 :         return CMD_SUCCESS;
    1921             : }
    1922             : 
    1923           0 : DEFUNSH(VTYSH_BGPD, vnc_l2_group, vnc_l2_group_cmd, "vnc l2-group NAME",
    1924             :         "VNC/RFP related configuration\n"
    1925             :         "Configure a L2 group\n"
    1926             :         "Group name\n")
    1927             : {
    1928           0 :         vty->node = BGP_VNC_L2_GROUP_NODE;
    1929           0 :         return CMD_SUCCESS;
    1930             : }
    1931             : 
    1932           0 : DEFUNSH(VTYSH_BGPD, exit_vnc_config, exit_vnc_config_cmd, "exit-vnc",
    1933             :         "Exit from VNC configuration mode\n")
    1934             : {
    1935           0 :         if (vty->node == BGP_VNC_DEFAULTS_NODE
    1936             :             || vty->node == BGP_VNC_NVE_GROUP_NODE
    1937           0 :             || vty->node == BGP_VNC_L2_GROUP_NODE)
    1938           0 :                 vty->node = BGP_NODE;
    1939           0 :         return CMD_SUCCESS;
    1940             : }
    1941             : 
    1942           0 : DEFUNSH(VTYSH_BGPD, exit_vrf_policy, exit_vrf_policy_cmd, "exit-vrf-policy",
    1943             :         "Exit from VRF policy configuration mode\n")
    1944             : {
    1945           0 :         if (vty->node == BGP_VRF_POLICY_NODE)
    1946           0 :                 vty->node = BGP_NODE;
    1947           0 :         return CMD_SUCCESS;
    1948             : }
    1949             : #endif
    1950             : #endif /* HAVE_BGPD */
    1951             : 
    1952           0 : DEFUNSH(VTYSH_KEYS, key_chain, key_chain_cmd, "key chain WORD",
    1953             :         "Authentication key management\n"
    1954             :         "Key-chain management\n"
    1955             :         "Key-chain name\n")
    1956             : {
    1957           0 :         vty->node = KEYCHAIN_NODE;
    1958           0 :         return CMD_SUCCESS;
    1959             : }
    1960             : 
    1961           0 : DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)",
    1962             :         "Configure a key\n"
    1963             :         "Key identifier number\n")
    1964             : {
    1965           0 :         vty->node = KEYCHAIN_KEY_NODE;
    1966           0 :         return CMD_SUCCESS;
    1967             : }
    1968             : 
    1969             : #ifdef HAVE_RIPD
    1970           0 : DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]",
    1971             :         ROUTER_STR "RIP\n" VRF_CMD_HELP_STR)
    1972             : {
    1973           0 :         vty->node = RIP_NODE;
    1974           0 :         return CMD_SUCCESS;
    1975             : }
    1976             : #endif /* HAVE_RIPD */
    1977             : 
    1978             : #ifdef HAVE_RIPNGD
    1979           0 : DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]",
    1980             :         ROUTER_STR "RIPng\n" VRF_CMD_HELP_STR)
    1981             : {
    1982           0 :         vty->node = RIPNG_NODE;
    1983           0 :         return CMD_SUCCESS;
    1984             : }
    1985             : #endif /* HAVE_RIPNGD */
    1986             : 
    1987             : #ifdef HAVE_OSPFD
    1988           0 : DEFUNSH(VTYSH_OSPFD, router_ospf, router_ospf_cmd,
    1989             :         "router ospf [(1-65535)] [vrf NAME]",
    1990             :         "Enable a routing process\n"
    1991             :         "Start OSPF configuration\n"
    1992             :         "Instance ID\n"
    1993             :         VRF_CMD_HELP_STR)
    1994             : {
    1995           0 :         vty->node = OSPF_NODE;
    1996           0 :         return CMD_SUCCESS;
    1997             : }
    1998             : #endif /* HAVE_OSPFD */
    1999             : 
    2000             : #ifdef HAVE_EIGRPD
    2001           0 : DEFUNSH(VTYSH_EIGRPD, router_eigrp, router_eigrp_cmd, "router eigrp (1-65535) [vrf NAME]",
    2002             :         "Enable a routing process\n"
    2003             :         "Start EIGRP configuration\n"
    2004             :         "AS number to use\n"
    2005             :         VRF_CMD_HELP_STR)
    2006             : {
    2007           0 :         vty->node = EIGRP_NODE;
    2008           0 :         return CMD_SUCCESS;
    2009             : }
    2010             : #endif /* HAVE_EIGRPD */
    2011             : 
    2012             : #ifdef HAVE_BABELD
    2013           0 : DEFUNSH(VTYSH_BABELD, router_babel, router_babel_cmd, "router babel",
    2014             :         "Enable a routing process\n"
    2015             :         "Make Babel instance command\n")
    2016             : {
    2017           0 :         vty->node = BABEL_NODE;
    2018           0 :         return CMD_SUCCESS;
    2019             : }
    2020             : #endif /* HAVE_BABELD */
    2021             : 
    2022             : #ifdef HAVE_OSPF6D
    2023           0 : DEFUNSH(VTYSH_OSPF6D, router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
    2024             :         ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
    2025             : {
    2026           0 :         vty->node = OSPF6_NODE;
    2027           0 :         return CMD_SUCCESS;
    2028             : }
    2029             : #endif
    2030             : 
    2031             : #if defined(HAVE_LDPD)
    2032           0 : DEFUNSH(VTYSH_LDPD, ldp_mpls_ldp, ldp_mpls_ldp_cmd, "mpls ldp",
    2033             :         "Global MPLS configuration subcommands\n"
    2034             :         "Label Distribution Protocol\n")
    2035             : {
    2036           0 :         vty->node = LDP_NODE;
    2037           0 :         return CMD_SUCCESS;
    2038             : }
    2039             : 
    2040           0 : DEFUNSH(VTYSH_LDPD, ldp_address_family_ipv4, ldp_address_family_ipv4_cmd,
    2041             :         "address-family ipv4",
    2042             :         "Configure Address Family and its parameters\n"
    2043             :         "IPv4\n")
    2044             : {
    2045           0 :         vty->node = LDP_IPV4_NODE;
    2046           0 :         return CMD_SUCCESS;
    2047             : }
    2048             : 
    2049           0 : DEFUNSH(VTYSH_LDPD, ldp_address_family_ipv6, ldp_address_family_ipv6_cmd,
    2050             :         "address-family ipv6",
    2051             :         "Configure Address Family and its parameters\n"
    2052             :         "IPv6\n")
    2053             : {
    2054           0 :         vty->node = LDP_IPV6_NODE;
    2055           0 :         return CMD_SUCCESS;
    2056             : }
    2057             : 
    2058           0 : DEFUNSH(VTYSH_LDPD, ldp_exit_address_family, ldp_exit_address_family_cmd,
    2059             :         "exit-address-family", "Exit from Address Family configuration mode\n")
    2060             : {
    2061           0 :         if (vty->node == LDP_IPV4_NODE || vty->node == LDP_IPV6_NODE)
    2062           0 :                 vty->node = LDP_NODE;
    2063           0 :         return CMD_SUCCESS;
    2064             : }
    2065             : 
    2066           0 : DEFUNSH(VTYSH_LDPD, ldp_interface_ifname, ldp_interface_ifname_cmd,
    2067             :         "interface IFNAME",
    2068             :         "Enable LDP on an interface and enter interface submode\n"
    2069             :         "Interface's name\n")
    2070             : {
    2071           0 :         switch (vty->node) {
    2072           0 :         case LDP_IPV4_NODE:
    2073           0 :                 vty->node = LDP_IPV4_IFACE_NODE;
    2074           0 :                 break;
    2075           0 :         case LDP_IPV6_NODE:
    2076           0 :                 vty->node = LDP_IPV6_IFACE_NODE;
    2077           0 :                 break;
    2078             :         default:
    2079             :                 break;
    2080             :         }
    2081             : 
    2082           0 :         return CMD_SUCCESS;
    2083             : }
    2084             : 
    2085           0 : DEFUNSH(VTYSH_LDPD, ldp_l2vpn_word_type_vpls, ldp_l2vpn_word_type_vpls_cmd,
    2086             :         "l2vpn WORD type vpls",
    2087             :         "Configure l2vpn commands\n"
    2088             :         "L2VPN name\n"
    2089             :         "L2VPN type\n"
    2090             :         "Virtual Private LAN Service\n")
    2091             : {
    2092           0 :         vty->node = LDP_L2VPN_NODE;
    2093           0 :         return CMD_SUCCESS;
    2094             : }
    2095             : 
    2096           0 : DEFUNSH(VTYSH_LDPD, ldp_member_pseudowire_ifname,
    2097             :         ldp_member_pseudowire_ifname_cmd, "member pseudowire IFNAME",
    2098             :         "L2VPN member configuration\n"
    2099             :         "Pseudowire interface\n"
    2100             :         "Interface's name\n")
    2101             : {
    2102           0 :         vty->node = LDP_PSEUDOWIRE_NODE;
    2103           0 :         return CMD_SUCCESS;
    2104             : }
    2105             : #endif
    2106             : 
    2107             : #ifdef HAVE_ISISD
    2108           0 : DEFUNSH(VTYSH_ISISD, router_isis, router_isis_cmd,
    2109             :         "router isis WORD [vrf NAME]",
    2110             :         ROUTER_STR
    2111             :         "ISO IS-IS\n"
    2112             :         "ISO Routing area tag\n" VRF_CMD_HELP_STR)
    2113             : {
    2114           0 :         vty->node = ISIS_NODE;
    2115           0 :         return CMD_SUCCESS;
    2116             : }
    2117             : #endif /* HAVE_ISISD */
    2118             : 
    2119             : #ifdef HAVE_FABRICD
    2120           0 : DEFUNSH(VTYSH_FABRICD, router_openfabric, router_openfabric_cmd, "router openfabric WORD",
    2121             :         ROUTER_STR
    2122             :         "OpenFabric routing protocol\n"
    2123             :         "ISO Routing area tag\n")
    2124             : {
    2125           0 :         vty->node = OPENFABRIC_NODE;
    2126           0 :         return CMD_SUCCESS;
    2127             : }
    2128             : #endif /* HAVE_FABRICD */
    2129             : 
    2130           0 : DEFUNSH(VTYSH_SR, segment_routing, segment_routing_cmd,
    2131             :         "segment-routing",
    2132             :         "Configure segment routing\n")
    2133             : {
    2134           0 :         vty->node = SEGMENT_ROUTING_NODE;
    2135           0 :         return CMD_SUCCESS;
    2136             : }
    2137             : 
    2138             : #if defined (HAVE_PATHD)
    2139           0 : DEFUNSH(VTYSH_PATHD, sr_traffic_eng, sr_traffic_eng_cmd,
    2140             :         "traffic-eng",
    2141             :         "Configure SR traffic engineering\n")
    2142             : {
    2143           0 :         vty->node = SR_TRAFFIC_ENG_NODE;
    2144           0 :         return CMD_SUCCESS;
    2145             : }
    2146             : 
    2147           0 : DEFUNSH(VTYSH_PATHD, srte_segment_list, srte_segment_list_cmd,
    2148             :         "segment-list WORD$name",
    2149             :         "Segment List\n"
    2150             :         "Segment List Name\n")
    2151             : {
    2152           0 :         vty->node = SR_SEGMENT_LIST_NODE;
    2153           0 :         return CMD_SUCCESS;
    2154             : }
    2155             : 
    2156           0 : DEFUNSH(VTYSH_PATHD, srte_policy, srte_policy_cmd,
    2157             :         "policy color (0-4294967295) endpoint <A.B.C.D|X:X::X:X>",
    2158             :         "Segment Routing Policy\n"
    2159             :         "SR Policy color\n"
    2160             :         "SR Policy color value\n"
    2161             :         "SR Policy endpoint\n"
    2162             :         "SR Policy endpoint IPv4 address\n"
    2163             :         "SR Policy endpoint IPv6 address\n")
    2164             : {
    2165           0 :         vty->node = SR_POLICY_NODE;
    2166           0 :         return CMD_SUCCESS;
    2167             : }
    2168             : 
    2169           0 : DEFUNSH(VTYSH_PATHD, srte_policy_candidate_dyn_path,
    2170             :         srte_policy_candidate_dyn_path_cmd,
    2171             :         "candidate-path preference (0-4294967295) name WORD dynamic",
    2172             :         "Segment Routing Policy Candidate Path\n"
    2173             :         "Segment Routing Policy Candidate Path Preference\n"
    2174             :         "Administrative Preference\n"
    2175             :         "Segment Routing Policy Candidate Path Name\n"
    2176             :         "Symbolic Name\n"
    2177             :         "Dynamic Path\n")
    2178             : {
    2179           0 :         vty->node = SR_CANDIDATE_DYN_NODE;
    2180           0 :         return CMD_SUCCESS;
    2181             : }
    2182             : 
    2183           0 : DEFUNSH(VTYSH_PATHD, pcep, pcep_cmd,
    2184             :         "pcep",
    2185             :         "Configure SR pcep\n")
    2186             : {
    2187           0 :         vty->node = PCEP_NODE;
    2188           0 :         return CMD_SUCCESS;
    2189             : }
    2190             : 
    2191           0 : DEFUNSH(VTYSH_PATHD, pcep_cli_pcc, pcep_cli_pcc_cmd,
    2192             :         "pcc",
    2193             :         "PCC configuration\n")
    2194             : {
    2195           0 :         vty->node = PCEP_PCC_NODE;
    2196           0 :         return CMD_SUCCESS;
    2197             : }
    2198             : 
    2199           0 : DEFUNSH(VTYSH_PATHD, pcep_cli_pce, pcep_cli_pce_cmd,
    2200             :         "pce WORD",
    2201             :         "PCE configuration\n"
    2202             :         "Peer name\n")
    2203             : {
    2204           0 :         vty->node = PCEP_PCE_NODE;
    2205           0 :         return CMD_SUCCESS;
    2206             : }
    2207             : 
    2208           0 : DEFUNSH(VTYSH_PATHD, pcep_cli_pcep_pce_config, pcep_cli_pcep_pce_config_cmd,
    2209             :         "pce-config WORD",
    2210             :         "PCEP peer Configuration Group\n"
    2211             :         "PCEP peer Configuration Group name\n")
    2212             : {
    2213           0 :         vty->node = PCEP_PCE_CONFIG_NODE;
    2214           0 :         return CMD_SUCCESS;
    2215             : }
    2216             : 
    2217             : #endif /* HAVE_PATHD */
    2218             : 
    2219           0 : DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd,
    2220             :         "route-map RMAP_NAME <deny|permit> (1-65535)",
    2221             :         "Create route-map or enter route-map command mode\n"
    2222             :         "Route map tag\n"
    2223             :         "Route map denies set operations\n"
    2224             :         "Route map permits set operations\n"
    2225             :         "Sequence to insert to/delete from existing route-map entry\n")
    2226             : {
    2227           0 :         vty->node = RMAP_NODE;
    2228           0 :         return CMD_SUCCESS;
    2229             : }
    2230             : 
    2231             : #ifdef HAVE_PBRD
    2232           0 : DEFUNSH(VTYSH_PBRD, vtysh_pbr_map, vtysh_pbr_map_cmd,
    2233             :         "pbr-map PBRMAP seq (1-700)",
    2234             :         "Create pbr-map or enter pbr-map command mode\n"
    2235             :         "The name of the PBR MAP\n"
    2236             :         "Sequence to insert to/delete from existing pbr-map entry\n"
    2237             :         "Sequence number\n")
    2238             : {
    2239           0 :         vty->node = PBRMAP_NODE;
    2240           0 :         return CMD_SUCCESS;
    2241             : }
    2242             : 
    2243             : DEFSH(VTYSH_PBRD, vtysh_no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]",
    2244             :         NO_STR
    2245             :         "Delete pbr-map\n"
    2246             :         "The name of  the PBR MAP\n"
    2247             :         "Sequence to delete from existing pbr-map entry\n"
    2248             :         "Sequence number\n")
    2249             : #endif /* HAVE_PBRD */
    2250             : 
    2251             : #if HAVE_BFDD > 0
    2252           0 : DEFUNSH(VTYSH_BFDD, bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n")
    2253             : {
    2254           0 :         vty->node = BFD_NODE;
    2255           0 :         return CMD_SUCCESS;
    2256             : }
    2257             : 
    2258           0 : DEFUNSH(VTYSH_BFDD, bfd_peer_enter, bfd_peer_enter_cmd,
    2259             :         "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
    2260             :         "Configure peer\n"
    2261             :         "IPv4 peer address\n"
    2262             :         "IPv6 peer address\n"
    2263             :         "Configure multihop\n"
    2264             :         "Configure local address\n"
    2265             :         "IPv4 local address\n"
    2266             :         "IPv6 local address\n"
    2267             :         INTERFACE_STR
    2268             :         "Configure interface name to use\n"
    2269             :         "Configure VRF\n"
    2270             :         "Configure VRF name\n")
    2271             : {
    2272           0 :         vty->node = BFD_PEER_NODE;
    2273           0 :         return CMD_SUCCESS;
    2274             : }
    2275             : 
    2276           0 : DEFUNSH(VTYSH_BFDD, bfd_profile_enter, bfd_profile_enter_cmd,
    2277             :         "profile BFDPROF",
    2278             :         BFD_PROFILE_STR
    2279             :         BFD_PROFILE_NAME_STR)
    2280             : {
    2281           0 :         vty->node = BFD_PROFILE_NODE;
    2282           0 :         return CMD_SUCCESS;
    2283             : }
    2284             : #endif /* HAVE_BFDD */
    2285             : 
    2286           1 : DEFUNSH(VTYSH_ALL, vtysh_line_vty, vtysh_line_vty_cmd, "line vty",
    2287             :         "Configure a terminal line\n"
    2288             :         "Virtual terminal\n")
    2289             : {
    2290           1 :         vty->node = VTY_NODE;
    2291           1 :         return CMD_SUCCESS;
    2292             : }
    2293             : 
    2294           2 : DEFUNSH(VTYSH_REALLYALL, vtysh_enable, vtysh_enable_cmd, "enable",
    2295             :         "Turn on privileged mode command\n")
    2296             : {
    2297           2 :         vty->node = ENABLE_NODE;
    2298           2 :         return CMD_SUCCESS;
    2299             : }
    2300             : 
    2301           2 : DEFUNSH(VTYSH_REALLYALL, vtysh_disable, vtysh_disable_cmd, "disable",
    2302             :         "Turn off privileged mode command\n")
    2303             : {
    2304           2 :         if (vty->node == ENABLE_NODE)
    2305           2 :                 vty->node = VIEW_NODE;
    2306           2 :         return CMD_SUCCESS;
    2307             : }
    2308             : 
    2309           2 : DEFUNSH(VTYSH_REALLYALL, vtysh_config_terminal, vtysh_config_terminal_cmd,
    2310             :         "configure [terminal]",
    2311             :         "Configuration from vty interface\n"
    2312             :         "Configuration terminal\n")
    2313             : {
    2314           2 :         vty->node = CONFIG_NODE;
    2315           2 :         return CMD_SUCCESS;
    2316             : }
    2317             : 
    2318           0 : static int vtysh_exit(struct vty *vty)
    2319             : {
    2320           0 :         struct cmd_node *cnode = vector_lookup(cmdvec, vty->node);
    2321             : 
    2322           0 :         if (vty->node == VIEW_NODE || vty->node == ENABLE_NODE)
    2323           0 :                 exit(0);
    2324           0 :         if (cnode->node_exit)
    2325           0 :                 cnode->node_exit(vty);
    2326           0 :         if (cnode->parent_node)
    2327           0 :                 vty->node = cnode->parent_node;
    2328             : 
    2329           0 :         if (vty->node == CONFIG_NODE) {
    2330             :                 /* resync in case one of the daemons is somewhere else */
    2331           0 :                 vtysh_execute("end");
    2332           0 :                 vtysh_execute("configure");
    2333             :         }
    2334           0 :         return CMD_SUCCESS;
    2335             : }
    2336             : 
    2337           0 : DEFUNSH(VTYSH_REALLYALL, vtysh_exit_all, vtysh_exit_all_cmd, "exit",
    2338             :         "Exit current mode and down to previous mode\n")
    2339             : {
    2340           0 :         return vtysh_exit(vty);
    2341             : }
    2342             : 
    2343           0 : DEFUNSH(VTYSH_REALLYALL, vtysh_quit_all, vtysh_quit_all_cmd, "quit",
    2344             :         "Exit current mode and down to previous mode\n")
    2345             : {
    2346           0 :         return vtysh_exit_all(self, vty, argc, argv);
    2347             : }
    2348             : 
    2349             : #ifdef HAVE_BGPD
    2350           0 : DEFUNSH(VTYSH_BGPD, exit_address_family, exit_address_family_cmd,
    2351             :         "exit-address-family", "Exit from Address Family configuration mode\n")
    2352             : {
    2353           0 :         if (vty->node == BGP_IPV4_NODE || vty->node == BGP_IPV4M_NODE
    2354           0 :             || vty->node == BGP_IPV4L_NODE || vty->node == BGP_VPNV4_NODE
    2355             :             || vty->node == BGP_VPNV6_NODE || vty->node == BGP_IPV6_NODE
    2356             :             || vty->node == BGP_IPV6L_NODE || vty->node == BGP_IPV6M_NODE
    2357             :             || vty->node == BGP_EVPN_NODE
    2358             :             || vty->node == BGP_FLOWSPECV4_NODE
    2359             :             || vty->node == BGP_FLOWSPECV6_NODE)
    2360           0 :                 vty->node = BGP_NODE;
    2361           0 :         return CMD_SUCCESS;
    2362             : }
    2363             : 
    2364           0 : DEFUNSH(VTYSH_BGPD, exit_vni, exit_vni_cmd, "exit-vni", "Exit from VNI mode\n")
    2365             : {
    2366           0 :         if (vty->node == BGP_EVPN_VNI_NODE)
    2367           0 :                 vty->node = BGP_EVPN_NODE;
    2368           0 :         return CMD_SUCCESS;
    2369             : }
    2370             : 
    2371           0 : DEFUNSH(VTYSH_BGPD, rpki_exit, rpki_exit_cmd, "exit",
    2372             :         "Exit current mode and down to previous mode\n")
    2373             : {
    2374           0 :         vtysh_exit(vty);
    2375           0 :         return CMD_SUCCESS;
    2376             : }
    2377             : 
    2378           0 : DEFUNSH(VTYSH_BGPD, rpki_quit, rpki_quit_cmd, "quit",
    2379             :         "Exit current mode and down to previous mode\n")
    2380             : {
    2381           0 :         return rpki_exit(self, vty, argc, argv);
    2382             : }
    2383             : 
    2384           0 : DEFUNSH(VTYSH_BGPD, bmp_exit, bmp_exit_cmd, "exit",
    2385             :         "Exit current mode and down to previous mode\n")
    2386             : {
    2387           0 :         vtysh_exit(vty);
    2388           0 :         return CMD_SUCCESS;
    2389             : }
    2390             : 
    2391           0 : DEFUNSH(VTYSH_BGPD, bmp_quit, bmp_quit_cmd, "quit",
    2392             :         "Exit current mode and down to previous mode\n")
    2393             : {
    2394           0 :         return bmp_exit(self, vty, argc, argv);
    2395             : }
    2396             : #endif /* HAVE_BGPD */
    2397             : 
    2398           0 : DEFUNSH(VTYSH_VRF, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf",
    2399             :         "Exit from VRF configuration mode\n")
    2400             : {
    2401           0 :         if (vty->node == VRF_NODE)
    2402           0 :                 vty->node = CONFIG_NODE;
    2403           0 :         return CMD_SUCCESS;
    2404             : }
    2405             : 
    2406           0 : DEFUNSH(VTYSH_ZEBRA, exit_srv6_config, exit_srv6_config_cmd, "exit",
    2407             :         "Exit from SRv6 configuration mode\n")
    2408             : {
    2409           0 :         if (vty->node == SRV6_NODE)
    2410           0 :                 vty->node = SEGMENT_ROUTING_NODE;
    2411           0 :         return CMD_SUCCESS;
    2412             : }
    2413             : 
    2414           0 : DEFUNSH(VTYSH_ZEBRA, exit_srv6_locs_config, exit_srv6_locs_config_cmd, "exit",
    2415             :         "Exit from SRv6-locator configuration mode\n")
    2416             : {
    2417           0 :         if (vty->node == SRV6_LOCS_NODE)
    2418           0 :                 vty->node = SRV6_NODE;
    2419           0 :         return CMD_SUCCESS;
    2420             : }
    2421             : 
    2422           0 : DEFUNSH(VTYSH_ZEBRA, exit_srv6_loc_config, exit_srv6_loc_config_cmd, "exit",
    2423             :         "Exit from SRv6-locators configuration mode\n")
    2424             : {
    2425           0 :         if (vty->node == SRV6_LOC_NODE)
    2426           0 :                 vty->node = SRV6_LOCS_NODE;
    2427           0 :         return CMD_SUCCESS;
    2428             : }
    2429             : 
    2430             : #ifdef HAVE_RIPD
    2431           0 : DEFUNSH(VTYSH_RIPD, vtysh_exit_ripd, vtysh_exit_ripd_cmd, "exit",
    2432             :         "Exit current mode and down to previous mode\n")
    2433             : {
    2434           0 :         return vtysh_exit(vty);
    2435             : }
    2436             : 
    2437           0 : DEFUNSH(VTYSH_RIPD, vtysh_quit_ripd, vtysh_quit_ripd_cmd, "quit",
    2438             :         "Exit current mode and down to previous mode\n")
    2439             : {
    2440           0 :         return vtysh_exit_ripd(self, vty, argc, argv);
    2441             : }
    2442             : #endif /* HAVE_RIPD */
    2443             : 
    2444             : #ifdef HAVE_RIPNGD
    2445           0 : DEFUNSH(VTYSH_RIPNGD, vtysh_exit_ripngd, vtysh_exit_ripngd_cmd, "exit",
    2446             :         "Exit current mode and down to previous mode\n")
    2447             : {
    2448           0 :         return vtysh_exit(vty);
    2449             : }
    2450             : 
    2451           0 : DEFUNSH(VTYSH_RIPNGD, vtysh_quit_ripngd, vtysh_quit_ripngd_cmd, "quit",
    2452             :         "Exit current mode and down to previous mode\n")
    2453             : {
    2454           0 :         return vtysh_exit_ripngd(self, vty, argc, argv);
    2455             : }
    2456             : #endif /* HAVE_RIPNGD */
    2457             : 
    2458           0 : DEFUNSH(VTYSH_RMAP, vtysh_exit_rmap, vtysh_exit_rmap_cmd, "exit",
    2459             :         "Exit current mode and down to previous mode\n")
    2460             : {
    2461           0 :         return vtysh_exit(vty);
    2462             : }
    2463             : 
    2464           0 : DEFUNSH(VTYSH_RMAP, vtysh_quit_rmap, vtysh_quit_rmap_cmd, "quit",
    2465             :         "Exit current mode and down to previous mode\n")
    2466             : {
    2467           0 :         return vtysh_exit_rmap(self, vty, argc, argv);
    2468             : }
    2469             : 
    2470             : #ifdef HAVE_PBRD
    2471           0 : DEFUNSH(VTYSH_PBRD, vtysh_exit_pbr_map, vtysh_exit_pbr_map_cmd, "exit",
    2472             :         "Exit current mode and down to previous mode\n")
    2473             : {
    2474           0 :         return vtysh_exit(vty);
    2475             : }
    2476             : 
    2477           0 : DEFUNSH(VTYSH_PBRD, vtysh_quit_pbr_map, vtysh_quit_pbr_map_cmd, "quit",
    2478             :         "Exit current mode and down to previous mode\n")
    2479             : {
    2480           0 :         return vtysh_exit_rmap(self, vty, argc, argv);
    2481             : }
    2482             : #endif /* HAVE_PBRD */
    2483             : 
    2484             : #ifdef HAVE_BGPD
    2485           0 : DEFUNSH(VTYSH_BGPD, vtysh_exit_bgpd, vtysh_exit_bgpd_cmd, "exit",
    2486             :         "Exit current mode and down to previous mode\n")
    2487             : {
    2488           0 :         return vtysh_exit(vty);
    2489             : }
    2490             : 
    2491           0 : DEFUNSH(VTYSH_BGPD, vtysh_quit_bgpd, vtysh_quit_bgpd_cmd, "quit",
    2492             :         "Exit current mode and down to previous mode\n")
    2493             : {
    2494           0 :         return vtysh_exit_bgpd(self, vty, argc, argv);
    2495             : }
    2496             : #endif /* HAVE_BGPD */
    2497             : 
    2498             : #ifdef HAVE_OSPFD
    2499           0 : DEFUNSH(VTYSH_OSPFD, vtysh_exit_ospfd, vtysh_exit_ospfd_cmd, "exit",
    2500             :         "Exit current mode and down to previous mode\n")
    2501             : {
    2502           0 :         return vtysh_exit(vty);
    2503             : }
    2504             : 
    2505           0 : DEFUNSH(VTYSH_OSPFD, vtysh_quit_ospfd, vtysh_quit_ospfd_cmd, "quit",
    2506             :         "Exit current mode and down to previous mode\n")
    2507             : {
    2508           0 :         return vtysh_exit_ospfd(self, vty, argc, argv);
    2509             : }
    2510             : #endif /* HAVE_OSPFD */
    2511             : 
    2512             : #ifdef HAVE_EIGRPD
    2513           0 : DEFUNSH(VTYSH_EIGRPD, vtysh_exit_eigrpd, vtysh_exit_eigrpd_cmd, "exit",
    2514             :         "Exit current mode and down to previous mode\n")
    2515             : {
    2516           0 :         return vtysh_exit(vty);
    2517             : }
    2518             : 
    2519           0 : DEFUNSH(VTYSH_EIGRPD, vtysh_quit_eigrpd, vtysh_quit_eigrpd_cmd, "quit",
    2520             :         "Exit current mode and down to previous mode\n")
    2521             : {
    2522           0 :         return vtysh_exit(vty);
    2523             : }
    2524             : #endif /* HAVE_EIGRPD */
    2525             : 
    2526             : #ifdef HAVE_BABELD
    2527           0 : DEFUNSH(VTYSH_BABELD, vtysh_exit_babeld, vtysh_exit_babeld_cmd, "exit",
    2528             :         "Exit current mode and down to previous mode\n")
    2529             : {
    2530           0 :         return vtysh_exit(vty);
    2531             : }
    2532             : 
    2533           0 : DEFUNSH(VTYSH_BABELD, vtysh_quit_babeld, vtysh_quit_babeld_cmd, "quit",
    2534             :         "Exit current mode and down to previous mode\n")
    2535             : {
    2536           0 :         return vtysh_exit(vty);
    2537             : }
    2538             : #endif /* HAVE_BABELD */
    2539             : 
    2540             : #ifdef HAVE_OSPF6D
    2541           0 : DEFUNSH(VTYSH_OSPF6D, vtysh_exit_ospf6d, vtysh_exit_ospf6d_cmd, "exit",
    2542             :         "Exit current mode and down to previous mode\n")
    2543             : {
    2544           0 :         return vtysh_exit(vty);
    2545             : }
    2546             : 
    2547           0 : DEFUNSH(VTYSH_OSPF6D, vtysh_quit_ospf6d, vtysh_quit_ospf6d_cmd, "quit",
    2548             :         "Exit current mode and down to previous mode\n")
    2549             : {
    2550           0 :         return vtysh_exit_ospf6d(self, vty, argc, argv);
    2551             : }
    2552             : #endif /* HAVE_OSPF6D */
    2553             : 
    2554             : #if defined(HAVE_LDPD)
    2555           0 : DEFUNSH(VTYSH_LDPD, vtysh_exit_ldpd, vtysh_exit_ldpd_cmd, "exit",
    2556             :         "Exit current mode and down to previous mode\n")
    2557             : {
    2558           0 :         return vtysh_exit(vty);
    2559             : }
    2560             : 
    2561             : ALIAS(vtysh_exit_ldpd, vtysh_quit_ldpd_cmd, "quit",
    2562             :       "Exit current mode and down to previous mode\n")
    2563             : #endif
    2564             : 
    2565             : #ifdef HAVE_ISISD
    2566           0 : DEFUNSH(VTYSH_ISISD, vtysh_exit_isisd, vtysh_exit_isisd_cmd, "exit",
    2567             :         "Exit current mode and down to previous mode\n")
    2568             : {
    2569           0 :         return vtysh_exit(vty);
    2570             : }
    2571             : 
    2572           0 : DEFUNSH(VTYSH_ISISD, vtysh_quit_isisd, vtysh_quit_isisd_cmd, "quit",
    2573             :         "Exit current mode and down to previous mode\n")
    2574             : {
    2575           0 :         return vtysh_exit_isisd(self, vty, argc, argv);
    2576             : }
    2577             : #endif /* HAVE_ISISD */
    2578             : 
    2579             : #if HAVE_BFDD > 0
    2580           0 : DEFUNSH(VTYSH_BFDD, vtysh_exit_bfdd, vtysh_exit_bfdd_cmd, "exit",
    2581             :         "Exit current mode and down to previous mode\n")
    2582             : {
    2583           0 :         return vtysh_exit(vty);
    2584             : }
    2585             : 
    2586             : ALIAS(vtysh_exit_bfdd, vtysh_quit_bfdd_cmd, "quit",
    2587             :       "Exit current mode and down to previous mode\n")
    2588             : #endif
    2589             : 
    2590             : #ifdef HAVE_FABRICD
    2591           0 : DEFUNSH(VTYSH_FABRICD, vtysh_exit_fabricd, vtysh_exit_fabricd_cmd, "exit",
    2592             :         "Exit current mode and down to previous mode\n")
    2593             : {
    2594           0 :         return vtysh_exit(vty);
    2595             : }
    2596             : 
    2597           0 : DEFUNSH(VTYSH_FABRICD, vtysh_quit_fabricd, vtysh_quit_fabricd_cmd, "quit",
    2598             :         "Exit current mode and down to previous mode\n")
    2599             : {
    2600           0 :         return vtysh_exit_fabricd(self, vty, argc, argv);
    2601             : }
    2602             : #endif /* HAVE_FABRICD */
    2603             : 
    2604           0 : DEFUNSH(VTYSH_KEYS, vtysh_exit_keys, vtysh_exit_keys_cmd, "exit",
    2605             :         "Exit current mode and down to previous mode\n")
    2606             : {
    2607           0 :         return vtysh_exit(vty);
    2608             : }
    2609             : 
    2610           0 : DEFUNSH(VTYSH_KEYS, vtysh_quit_keys, vtysh_quit_keys_cmd, "quit",
    2611             :         "Exit current mode and down to previous mode\n")
    2612             : {
    2613           0 :         return vtysh_exit_keys(self, vty, argc, argv);
    2614             : }
    2615             : 
    2616           0 : DEFUNSH(VTYSH_SR, vtysh_exit_sr, vtysh_exit_sr_cmd, "exit",
    2617             :         "Exit current mode and down to previous mode\n")
    2618             : {
    2619           0 :         return vtysh_exit(vty);
    2620             : }
    2621             : 
    2622           0 : DEFUNSH(VTYSH_SR, vtysh_quit_sr, vtysh_quit_sr_cmd, "quit",
    2623             :         "Exit current mode and down to previous mode\n")
    2624             : {
    2625           0 :         return vtysh_exit(vty);
    2626             : }
    2627             : 
    2628             : #if defined(HAVE_PATHD)
    2629           0 : DEFUNSH(VTYSH_PATHD, vtysh_exit_pathd, vtysh_exit_pathd_cmd, "exit",
    2630             :         "Exit current mode and down to previous mode\n")
    2631             : {
    2632           0 :         return vtysh_exit(vty);
    2633             : }
    2634             : 
    2635           0 : DEFUNSH(VTYSH_PATHD, vtysh_quit_pathd, vtysh_quit_pathd_cmd, "quit",
    2636             :         "Exit current mode and down to previous mode\n")
    2637             : {
    2638           0 :         return vtysh_exit_pathd(self, vty, argc, argv);
    2639             : }
    2640             : #endif /* HAVE_PATHD */
    2641             : 
    2642           0 : DEFUNSH(VTYSH_ALL, vtysh_exit_line_vty, vtysh_exit_line_vty_cmd, "exit",
    2643             :         "Exit current mode and down to previous mode\n")
    2644             : {
    2645           0 :         return vtysh_exit(vty);
    2646             : }
    2647             : 
    2648           0 : DEFUNSH(VTYSH_ALL, vtysh_quit_line_vty, vtysh_quit_line_vty_cmd, "quit",
    2649             :         "Exit current mode and down to previous mode\n")
    2650             : {
    2651           0 :         return vtysh_exit_line_vty(self, vty, argc, argv);
    2652             : }
    2653             : 
    2654           0 : DEFUNSH(VTYSH_INTERFACE, vtysh_interface, vtysh_interface_cmd,
    2655             :         "interface IFNAME [vrf NAME]",
    2656             :         "Select an interface to configure\n"
    2657             :         "Interface's name\n" VRF_CMD_HELP_STR)
    2658             : {
    2659           0 :         vty->node = INTERFACE_NODE;
    2660           0 :         return CMD_SUCCESS;
    2661             : }
    2662             : 
    2663           0 : DEFUNSH(VTYSH_ZEBRA, vtysh_pseudowire, vtysh_pseudowire_cmd,
    2664             :         "pseudowire IFNAME",
    2665             :         "Static pseudowire configuration\n"
    2666             :         "Pseudowire name\n")
    2667             : {
    2668           0 :         vty->node = PW_NODE;
    2669           0 :         return CMD_SUCCESS;
    2670             : }
    2671             : 
    2672           0 : DEFUNSH(VTYSH_NH_GROUP,
    2673             :         vtysh_nexthop_group, vtysh_nexthop_group_cmd,
    2674             :         "nexthop-group NHGNAME",
    2675             :         "Nexthop Group configuration\n"
    2676             :         "Name of the Nexthop Group\n")
    2677             : {
    2678           0 :         vty->node = NH_GROUP_NODE;
    2679           0 :         return CMD_SUCCESS;
    2680             : }
    2681             : 
    2682             : DEFSH(VTYSH_NH_GROUP, vtysh_no_nexthop_group_cmd,
    2683             :       "no nexthop-group NHGNAME",
    2684             :       NO_STR
    2685             :       "Nexthop Group Configuration\n"
    2686             :       "Name of the Nexthop Group\n")
    2687             : 
    2688           0 : DEFUNSH(VTYSH_VRF, vtysh_vrf, vtysh_vrf_cmd, "vrf NAME",
    2689             :         "Select a VRF to configure\n"
    2690             :         "VRF's name\n")
    2691             : {
    2692           0 :         vty->node = VRF_NODE;
    2693           0 :         return CMD_SUCCESS;
    2694             : }
    2695             : 
    2696           0 : DEFUNSH(VTYSH_VRF, vtysh_exit_vrf, vtysh_exit_vrf_cmd, "exit",
    2697             :         "Exit current mode and down to previous mode\n")
    2698             : {
    2699           0 :         return vtysh_exit(vty);
    2700             : }
    2701             : 
    2702           0 : DEFUNSH(VTYSH_VRF, vtysh_quit_vrf, vtysh_quit_vrf_cmd, "quit",
    2703             :         "Exit current mode and down to previous mode\n")
    2704             : {
    2705           0 :         return vtysh_exit_vrf(self, vty, argc, argv);
    2706             : }
    2707             : 
    2708           0 : DEFUNSH(VTYSH_NH_GROUP,
    2709             :         vtysh_exit_nexthop_group, vtysh_exit_nexthop_group_cmd,
    2710             :         "exit", "Exit current mode and down to previous mode\n")
    2711             : {
    2712           0 :         return vtysh_exit(vty);
    2713             : }
    2714             : 
    2715           0 : DEFUNSH(VTYSH_NH_GROUP,
    2716             :         vtysh_quit_nexthop_group, vtysh_quit_nexthop_group_cmd,
    2717             :         "quit", "Exit current mode and down to previous mode\n")
    2718             : {
    2719           0 :         return vtysh_exit_nexthop_group(self, vty, argc, argv);
    2720             : }
    2721             : 
    2722           0 : DEFUNSH(VTYSH_INTERFACE, vtysh_exit_interface, vtysh_exit_interface_cmd, "exit",
    2723             :         "Exit current mode and down to previous mode\n")
    2724             : {
    2725           0 :         return vtysh_exit(vty);
    2726             : }
    2727             : 
    2728           0 : DEFUNSH(VTYSH_INTERFACE, vtysh_quit_interface, vtysh_quit_interface_cmd, "quit",
    2729             :         "Exit current mode and down to previous mode\n")
    2730             : {
    2731           0 :         return vtysh_exit_interface(self, vty, argc, argv);
    2732             : }
    2733             : 
    2734           0 : DEFUNSH(VTYSH_ZEBRA, vtysh_exit_pseudowire, vtysh_exit_pseudowire_cmd, "exit",
    2735             :         "Exit current mode and down to previous mode\n")
    2736             : {
    2737           0 :         return vtysh_exit(vty);
    2738             : }
    2739             : 
    2740           0 : DEFUNSH(VTYSH_ZEBRA, vtysh_quit_pseudowire, vtysh_quit_pseudowire_cmd, "quit",
    2741             :         "Exit current mode and down to previous mode\n")
    2742             : {
    2743           0 :         return vtysh_exit_pseudowire(self, vty, argc, argv);
    2744             : }
    2745             : 
    2746           0 : static char *do_prepend(struct vty *vty, struct cmd_token **argv, int argc)
    2747           0 : {
    2748           0 :         const char *argstr[argc + 1];
    2749           0 :         int i, off = 0;
    2750             : 
    2751           0 :         if (vty->node != VIEW_NODE) {
    2752           0 :                 off = 1;
    2753           0 :                 argstr[0] = "do";
    2754             :         }
    2755             : 
    2756           0 :         for (i = 0; i < argc; i++)
    2757           0 :                 argstr[i + off] = argv[i]->arg;
    2758             : 
    2759           0 :         return frrstr_join(argstr, argc + off, " ");
    2760             : }
    2761             : 
    2762             : #pragma GCC diagnostic push
    2763             : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
    2764             : /* 'headline' is a format string with a %s for the daemon name
    2765             :  *
    2766             :  * Also for some reason GCC emits the warning on the end of the function
    2767             :  * (optimization maybe?) rather than on the vty_out line, so this pragma
    2768             :  * wraps the entire function rather than just the vty_out line.
    2769             :  */
    2770             : 
    2771           0 : static int show_per_daemon(struct vty *vty, struct cmd_token **argv, int argc,
    2772             :                            const char *headline)
    2773             : {
    2774           0 :         unsigned int i;
    2775           0 :         int ret = CMD_SUCCESS;
    2776           0 :         char *line = do_prepend(vty, argv, argc);
    2777             : 
    2778           0 :         for (i = 0; i < array_size(vtysh_client); i++)
    2779           0 :                 if (vtysh_client[i].fd >= 0 || vtysh_client[i].next) {
    2780           0 :                         vty_out(vty, headline, vtysh_client[i].name);
    2781           0 :                         ret = vtysh_client_execute(&vtysh_client[i], line);
    2782           0 :                         vty_out(vty, "\n");
    2783             :                 }
    2784             : 
    2785           0 :         XFREE(MTYPE_TMP, line);
    2786             : 
    2787           0 :         return ret;
    2788             : }
    2789             : #pragma GCC diagnostic pop
    2790             : 
    2791           0 : static int show_one_daemon(struct vty *vty, struct cmd_token **argv, int argc,
    2792             :                            const char *name)
    2793             : {
    2794           0 :         int ret;
    2795           0 :         char *line = do_prepend(vty, argv, argc);
    2796             : 
    2797           0 :         ret = vtysh_client_execute_name(name, line);
    2798             : 
    2799           0 :         XFREE(MTYPE_TMP, line);
    2800             : 
    2801           0 :         return ret;
    2802             : }
    2803             : 
    2804           0 : DEFUN (vtysh_show_thread_timer,
    2805             :        vtysh_show_thread_timer_cmd,
    2806             :        "show thread timers",
    2807             :        SHOW_STR
    2808             :        "Thread information\n"
    2809             :        "Show all timers and how long they have in the system\n")
    2810             : {
    2811           0 :         return show_per_daemon(vty, argv, argc, "Thread timers for %s:\n");
    2812             : }
    2813             : 
    2814           0 : DEFUN (vtysh_show_poll,
    2815             :        vtysh_show_poll_cmd,
    2816             :        "show thread poll",
    2817             :        SHOW_STR
    2818             :        "Thread information\n"
    2819             :        "Thread Poll Information\n")
    2820             : {
    2821           0 :         return show_per_daemon(vty, argv, argc, "Thread statistics for %s:\n");
    2822             : }
    2823             : 
    2824           0 : DEFUN (vtysh_show_thread,
    2825             :        vtysh_show_thread_cmd,
    2826             :        "show thread cpu [FILTER]",
    2827             :        SHOW_STR
    2828             :        "Thread information\n"
    2829             :        "Thread CPU usage\n"
    2830             :        "Display filter (rwtexb)\n")
    2831             : {
    2832           0 :         return show_per_daemon(vty, argv, argc, "Thread statistics for %s:\n");
    2833             : }
    2834             : 
    2835           0 : DEFUN (vtysh_show_work_queues,
    2836             :        vtysh_show_work_queues_cmd,
    2837             :        "show work-queues",
    2838             :        SHOW_STR
    2839             :        "Work Queue information\n")
    2840             : {
    2841           0 :         return show_per_daemon(vty, argv, argc,
    2842             :                                "Work queue statistics for %s:\n");
    2843             : }
    2844             : 
    2845           0 : DEFUN (vtysh_show_work_queues_daemon,
    2846             :        vtysh_show_work_queues_daemon_cmd,
    2847             :        "show work-queues " DAEMONS_LIST,
    2848             :        SHOW_STR
    2849             :        "Work Queue information\n"
    2850             :        DAEMONS_STR)
    2851             : {
    2852           0 :         return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
    2853             : }
    2854             : 
    2855           0 : DEFUNSH(VTYSH_ZEBRA, vtysh_link_params, vtysh_link_params_cmd, "link-params",
    2856             :         LINK_PARAMS_STR)
    2857             : {
    2858           0 :         vty->node = LINK_PARAMS_NODE;
    2859           0 :         return CMD_SUCCESS;
    2860             : }
    2861             : 
    2862           0 : DEFUNSH(VTYSH_ZEBRA, exit_link_params, exit_link_params_cmd, "exit-link-params",
    2863             :         "Exit from Link Params configuration node\n")
    2864             : {
    2865           0 :         if (vty->node == LINK_PARAMS_NODE)
    2866           0 :                 vty->node = INTERFACE_NODE;
    2867           0 :         return CMD_SUCCESS;
    2868             : }
    2869             : 
    2870           0 : DEFUNSH(VTYSH_ZEBRA, vtysh_exit_link_params, vtysh_exit_link_params_cmd, "exit",
    2871             :         "Exit current mode and down to previous mode\n")
    2872             : {
    2873           0 :         if (vty->node == LINK_PARAMS_NODE)
    2874           0 :                 vty->node = INTERFACE_NODE;
    2875           0 :         return CMD_SUCCESS;
    2876             : }
    2877             : 
    2878           0 : DEFUNSH(VTYSH_ZEBRA, vtysh_quit_link_params, vtysh_quit_link_params_cmd, "quit",
    2879             :         "Exit current mode and down to previous mode\n")
    2880             : {
    2881           0 :         return vtysh_exit_link_params(self, vty, argc, argv);
    2882             : }
    2883             : 
    2884           0 : DEFUNSH_HIDDEN (0x00,
    2885             :                 vtysh_debug_all,
    2886             :                 vtysh_debug_all_cmd,
    2887             :                 "[no] debug all",
    2888             :                 NO_STR
    2889             :                 DEBUG_STR
    2890             :                 "Toggle all debugs on or off\n")
    2891             : {
    2892           0 :         return CMD_SUCCESS;
    2893             : }
    2894             : 
    2895           0 : DEFUN (vtysh_show_debugging,
    2896             :        vtysh_show_debugging_cmd,
    2897             :        "show debugging",
    2898             :        SHOW_STR
    2899             :        DEBUG_STR)
    2900             : {
    2901           0 :         return show_per_daemon(vty, argv, argc, "");
    2902             : }
    2903             : 
    2904           0 : DEFUN (vtysh_show_debugging_hashtable,
    2905             :        vtysh_show_debugging_hashtable_cmd,
    2906             :        "show debugging hashtable [statistics]",
    2907             :        SHOW_STR
    2908             :        DEBUG_STR
    2909             :        "Statistics about hash tables\n"
    2910             :        "Statistics about hash tables\n")
    2911             : {
    2912           0 :         bool stats = strmatch(argv[argc - 1]->text, "statistics");
    2913             : 
    2914           0 :         vty_out(vty, "\n");
    2915           0 :         vty_out(vty,
    2916             :                 "Load factor (LF) - average number of elements across all buckets\n");
    2917           0 :         vty_out(vty,
    2918             :                 "Full load factor (FLF) - average number of elements across full buckets\n\n");
    2919           0 :         vty_out(vty,
    2920             :                 "Standard deviation (SD) is calculated for both the LF and FLF\n");
    2921           0 :         vty_out(vty,
    2922             :                 "and indicates the typical deviation of bucket chain length\n");
    2923           0 :         vty_out(vty, "from the value in the corresponding load factor.\n\n");
    2924             : 
    2925           0 :         return show_per_daemon(vty, argv, stats ? argc - 1 : argc,
    2926             :                                "Hashtable statistics for %s:\n");
    2927             : }
    2928             : 
    2929           0 : DEFUN (vtysh_show_error_code,
    2930             :        vtysh_show_error_code_cmd,
    2931             :        "show error <(1-4294967296)|all> [json]",
    2932             :        SHOW_STR
    2933             :        "Information on errors\n"
    2934             :        "Error code to get info about\n"
    2935             :        "Information on all errors\n"
    2936             :        JSON_STR)
    2937             : {
    2938           0 :         uint32_t arg = 0;
    2939             : 
    2940           0 :         if (!strmatch(argv[2]->text, "all"))
    2941           0 :                 arg = strtoul(argv[2]->arg, NULL, 10);
    2942             : 
    2943             :         /* If it's not a shared code, send it to all the daemons */
    2944           0 :         if (arg < LIB_FERR_START || arg > LIB_FERR_END) {
    2945           0 :                 show_per_daemon(vty, argv, argc, "");
    2946             :                 /* Otherwise, print it ourselves to avoid duplication */
    2947             :         } else {
    2948           0 :                 bool json = strmatch(argv[argc - 1]->text, "json");
    2949             : 
    2950           0 :                 if (!strmatch(argv[2]->text, "all"))
    2951           0 :                         arg = strtoul(argv[2]->arg, NULL, 10);
    2952             : 
    2953           0 :                 log_ref_display(vty, arg, json);
    2954             :         }
    2955             : 
    2956           0 :         return CMD_SUCCESS;
    2957             : }
    2958             : 
    2959             : /* Northbound. */
    2960           0 : DEFUN_HIDDEN (show_config_running,
    2961             :        show_config_running_cmd,
    2962             :        "show configuration running\
    2963             :           [<json|xml> [translate WORD]]\
    2964             :           [with-defaults] " DAEMONS_LIST,
    2965             :        SHOW_STR
    2966             :        "Configuration information\n"
    2967             :        "Running configuration\n"
    2968             :        "Change output format to JSON\n"
    2969             :        "Change output format to XML\n"
    2970             :        "Translate output\n"
    2971             :        "YANG module translator\n"
    2972             :        "Show default values\n"
    2973             :        DAEMONS_STR)
    2974             : {
    2975           0 :         return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
    2976             : }
    2977             : 
    2978           0 : DEFUN (show_yang_operational_data,
    2979             :        show_yang_operational_data_cmd,
    2980             :        "show yang operational-data XPATH\
    2981             :          [{\
    2982             :            format <json|xml>\
    2983             :            |translate WORD\
    2984             :            |with-config\
    2985             :          }] " DAEMONS_LIST,
    2986             :        SHOW_STR
    2987             :        "YANG information\n"
    2988             :        "Show YANG operational data\n"
    2989             :        "XPath expression specifying the YANG data path\n"
    2990             :        "Set the output format\n"
    2991             :        "JavaScript Object Notation\n"
    2992             :        "Extensible Markup Language\n"
    2993             :        "Translate operational data\n"
    2994             :        "YANG module translator\n"
    2995             :        "Merge configuration data\n"
    2996             :        DAEMONS_STR)
    2997             : {
    2998           0 :         return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
    2999             : }
    3000             : 
    3001           0 : DEFUN(show_yang_module, show_yang_module_cmd,
    3002             :       "show yang module [module-translator WORD] " DAEMONS_LIST,
    3003             :       SHOW_STR
    3004             :       "YANG information\n"
    3005             :       "Show loaded modules\n"
    3006             :       "YANG module translator\n"
    3007             :       "YANG module translator\n" DAEMONS_STR)
    3008             : {
    3009           0 :         return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
    3010             : }
    3011             : 
    3012           0 : DEFUN(show_yang_module_detail, show_yang_module_detail_cmd,
    3013             :       "show yang module\
    3014             :           [module-translator WORD]\
    3015             :           WORD <compiled|summary|tree|yang|yin> " DAEMONS_LIST,
    3016             :       SHOW_STR
    3017             :       "YANG information\n"
    3018             :       "Show loaded modules\n"
    3019             :       "YANG module translator\n"
    3020             :       "YANG module translator\n"
    3021             :       "Module name\n"
    3022             :       "Display compiled module in YANG format\n"
    3023             :       "Display summary information about the module\n"
    3024             :       "Display module in the tree (RFC 8340) format\n"
    3025             :       "Display module in the YANG format\n"
    3026             :       "Display module in the YIN format\n" DAEMONS_STR)
    3027             : {
    3028           0 :         return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
    3029             : }
    3030             : 
    3031             : 
    3032           0 : DEFUNSH(VTYSH_ALL, debug_nb,
    3033             :         debug_nb_cmd,
    3034             :         "[no] debug northbound\
    3035             :            [<\
    3036             :             callbacks [{configuration|state|rpc}]\
    3037             :             |notifications\
    3038             :             |events\
    3039             :             |libyang\
    3040             :            >]",
    3041             :         NO_STR
    3042             :         DEBUG_STR
    3043             :         "Northbound debugging\n"
    3044             :         "Callbacks\n"
    3045             :         "Configuration\n"
    3046             :         "State\n"
    3047             :         "RPC\n"
    3048             :         "Notifications\n"
    3049             :         "Events\n"
    3050             :         "libyang debugging\n")
    3051             : {
    3052           0 :         return CMD_SUCCESS;
    3053             : }
    3054             : 
    3055           0 : DEFUN (vtysh_show_history,
    3056             :        vtysh_show_history_cmd,
    3057             :        "show history",
    3058             :        SHOW_STR
    3059             :        "The list of commands stored in history\n")
    3060             : {
    3061           0 :         HIST_ENTRY **hlist = history_list();
    3062           0 :         int i = 0;
    3063             : 
    3064           0 :         while (hlist[i]) {
    3065           0 :                 vty_out(vty, "%s\n", hlist[i]->line);
    3066           0 :                 i++;
    3067             :         }
    3068           0 :         return CMD_SUCCESS;
    3069             : }
    3070             : 
    3071             : /* Memory */
    3072           0 : DEFUN (vtysh_show_memory,
    3073             :        vtysh_show_memory_cmd,
    3074             :        "show memory [" DAEMONS_LIST "]",
    3075             :        SHOW_STR
    3076             :        "Memory statistics\n"
    3077             :        DAEMONS_STR)
    3078             : {
    3079           0 :         if (argc == 3)
    3080           0 :                 return show_one_daemon(vty, argv, argc - 1,
    3081           0 :                                        argv[argc - 1]->text);
    3082             : 
    3083           0 :         return show_per_daemon(vty, argv, argc, "Memory statistics for %s:\n");
    3084             : }
    3085             : 
    3086           0 : DEFUN (vtysh_show_modules,
    3087             :        vtysh_show_modules_cmd,
    3088             :        "show modules",
    3089             :        SHOW_STR
    3090             :        "Loaded modules\n")
    3091             : {
    3092           0 :         return show_per_daemon(vty, argv, argc, "Module information for %s:\n");
    3093             : }
    3094             : 
    3095             : /* Logging commands. */
    3096           0 : DEFUN (vtysh_show_logging,
    3097             :        vtysh_show_logging_cmd,
    3098             :        "show logging",
    3099             :        SHOW_STR
    3100             :        "Show current logging configuration\n")
    3101             : {
    3102           0 :         return show_per_daemon(vty, argv, argc,
    3103             :                                "Logging configuration for %s:\n");
    3104             : }
    3105             : 
    3106           0 : DEFUNSH(VTYSH_ALL, vtysh_debug_memstats,
    3107             :         vtysh_debug_memstats_cmd, "[no] debug memstats-at-exit",
    3108             :         NO_STR
    3109             :         "Debug\n"
    3110             :         "Print memory statistics at exit\n")
    3111             : {
    3112           0 :         return CMD_SUCCESS;
    3113             : }
    3114             : 
    3115           0 : DEFUN(vtysh_debug_uid_backtrace,
    3116             :       vtysh_debug_uid_backtrace_cmd,
    3117             :       "[no] debug unique-id UID backtrace",
    3118             :       NO_STR
    3119             :       DEBUG_STR
    3120             :       "Options per individual log message, by unique ID\n"
    3121             :       "Log message unique ID (XXXXX-XXXXX)\n"
    3122             :       "Add backtrace to log when message is printed\n")
    3123             : {
    3124           0 :         unsigned int i, ok = 0;
    3125           0 :         int err = CMD_SUCCESS, ret;
    3126           0 :         const char *uid;
    3127           0 :         char line[64];
    3128             : 
    3129           0 :         if (!strcmp(argv[0]->text, "no")) {
    3130           0 :                 uid = argv[3]->arg;
    3131           0 :                 snprintfrr(line, sizeof(line),
    3132             :                            "no debug unique-id %s backtrace", uid);
    3133             :         } else {
    3134           0 :                 uid = argv[2]->arg;
    3135           0 :                 snprintfrr(line, sizeof(line), "debug unique-id %s backtrace",
    3136             :                            uid);
    3137             :         }
    3138             : 
    3139           0 :         for (i = 0; i < array_size(vtysh_client); i++)
    3140           0 :                 if (vtysh_client[i].fd >= 0 || vtysh_client[i].next) {
    3141           0 :                         ret = vtysh_client_execute(&vtysh_client[i], line);
    3142           0 :                         switch (ret) {
    3143           0 :                         case CMD_SUCCESS:
    3144           0 :                                 ok++;
    3145           0 :                                 break;
    3146             :                         case CMD_ERR_NOTHING_TODO:
    3147             :                                 /* ignore this daemon
    3148             :                                  *
    3149             :                                  * note this doesn't need to handle instances
    3150             :                                  * of the same daemon individually because
    3151             :                                  * the same daemon will have the same UIDs
    3152             :                                  */
    3153             :                                 break;
    3154           0 :                         default:
    3155           0 :                                 if (err == CMD_SUCCESS)
    3156           0 :                                         err = ret;
    3157             :                                 break;
    3158             :                         }
    3159             :                 }
    3160             : 
    3161           0 :         if (err == CMD_SUCCESS && !ok) {
    3162           0 :                 vty_out(vty, "%% no running daemon recognizes unique-ID %s\n",
    3163             :                         uid);
    3164           0 :                 err = CMD_WARNING;
    3165             :         }
    3166           0 :         return err;
    3167             : }
    3168             : 
    3169           0 : DEFUNSH(VTYSH_ALL, vtysh_allow_reserved_ranges, vtysh_allow_reserved_ranges_cmd,
    3170             :         "allow-reserved-ranges",
    3171             :         "Allow using IPv4 (Class E) reserved IP space\n")
    3172             : {
    3173           0 :         return CMD_SUCCESS;
    3174             : }
    3175             : 
    3176           0 : DEFUNSH(VTYSH_ALL, no_vtysh_allow_reserved_ranges,
    3177             :         no_vtysh_allow_reserved_ranges_cmd, "no allow-reserved-ranges",
    3178             :         NO_STR "Allow using IPv4 (Class E) reserved IP space\n")
    3179             : {
    3180           0 :         return CMD_SUCCESS;
    3181             : }
    3182             : 
    3183           0 : DEFUNSH(VTYSH_ALL, vtysh_service_password_encrypt,
    3184             :         vtysh_service_password_encrypt_cmd, "service password-encryption",
    3185             :         "Set up miscellaneous service\n"
    3186             :         "Enable encrypted passwords\n")
    3187             : {
    3188           0 :         return CMD_SUCCESS;
    3189             : }
    3190             : 
    3191           0 : DEFUNSH(VTYSH_ALL, no_vtysh_service_password_encrypt,
    3192             :         no_vtysh_service_password_encrypt_cmd, "no service password-encryption",
    3193             :         NO_STR
    3194             :         "Set up miscellaneous service\n"
    3195             :         "Enable encrypted passwords\n")
    3196             : {
    3197           0 :         return CMD_SUCCESS;
    3198             : }
    3199             : 
    3200           0 : DEFUNSH(VTYSH_ALL, vtysh_config_password, vtysh_password_cmd,
    3201             :         "password [(8-8)] LINE",
    3202             :         "Modify the terminal connection password\n"
    3203             :         "Specifies a HIDDEN password will follow\n"
    3204             :         "The password string\n")
    3205             : {
    3206           0 :         return CMD_SUCCESS;
    3207             : }
    3208             : 
    3209           0 : DEFUNSH(VTYSH_ALL, no_vtysh_config_password, no_vtysh_password_cmd,
    3210             :         "no password", NO_STR
    3211             :         "Modify the terminal connection password\n")
    3212             : {
    3213           0 :         vty_out(vty, NO_PASSWD_CMD_WARNING);
    3214             : 
    3215           0 :         return CMD_SUCCESS;
    3216             : }
    3217             : 
    3218           0 : DEFUNSH(VTYSH_ALL, vtysh_config_enable_password, vtysh_enable_password_cmd,
    3219             :         "enable password [(8-8)] LINE",
    3220             :         "Modify enable password parameters\n"
    3221             :         "Assign the privileged level password\n"
    3222             :         "Specifies a HIDDEN password will follow\n"
    3223             :         "The 'enable' password string\n")
    3224             : {
    3225           0 :         return CMD_SUCCESS;
    3226             : }
    3227             : 
    3228           0 : DEFUNSH(VTYSH_ALL, no_vtysh_config_enable_password,
    3229             :         no_vtysh_enable_password_cmd, "no enable password", NO_STR
    3230             :         "Modify enable password parameters\n"
    3231             :         "Assign the privileged level password\n")
    3232             : {
    3233           0 :         vty_out(vty, NO_PASSWD_CMD_WARNING);
    3234             : 
    3235           0 :         return CMD_SUCCESS;
    3236             : }
    3237             : 
    3238           0 : DEFUN (vtysh_write_terminal,
    3239             :        vtysh_write_terminal_cmd,
    3240             :        "write terminal ["DAEMONS_LIST"] [no-header]",
    3241             :        "Write running configuration to memory, network, or terminal\n"
    3242             :        "Write to terminal\n"
    3243             :        DAEMONS_STR
    3244             :        "Skip \"Building configuration...\" header\n")
    3245             : {
    3246           0 :         unsigned int i;
    3247           0 :         char line[] = "do write terminal";
    3248             : 
    3249           0 :         if (!strcmp(argv[argc - 1]->arg, "no-header"))
    3250           0 :                 argc--;
    3251             :         else {
    3252           0 :                 vty_out(vty, "Building configuration...\n");
    3253           0 :                 vty_out(vty, "\nCurrent configuration:\n");
    3254           0 :                 vty_out(vty, "!\n");
    3255             :         }
    3256             : 
    3257           0 :         for (i = 0; i < array_size(vtysh_client); i++)
    3258           0 :                 if ((argc < 3)
    3259           0 :                     || (strmatch(vtysh_client[i].name, argv[2]->text)))
    3260           0 :                         vtysh_client_config(&vtysh_client[i], line);
    3261             : 
    3262             :         /* Integrate vtysh specific configuration. */
    3263           0 :         vty_open_pager(vty);
    3264           0 :         vtysh_config_write();
    3265           0 :         vtysh_config_dump();
    3266           0 :         vty_close_pager(vty);
    3267           0 :         vty_out(vty, "end\n");
    3268             : 
    3269           0 :         return CMD_SUCCESS;
    3270             : }
    3271             : 
    3272           0 : DEFUN (vtysh_show_running_config,
    3273             :        vtysh_show_running_config_cmd,
    3274             :        "show running-config ["DAEMONS_LIST"] [no-header]",
    3275             :        SHOW_STR
    3276             :        "Current operating configuration\n"
    3277             :        DAEMONS_STR
    3278             :        "Skip \"Building configuration...\" header\n")
    3279             : {
    3280           0 :         return vtysh_write_terminal(self, vty, argc, argv);
    3281             : }
    3282             : 
    3283           0 : DEFUN (vtysh_integrated_config,
    3284             :        vtysh_integrated_config_cmd,
    3285             :        "service integrated-vtysh-config",
    3286             :        "Set up miscellaneous service\n"
    3287             :        "Write configuration into integrated file\n")
    3288             : {
    3289           0 :         vtysh_write_integrated = WRITE_INTEGRATED_YES;
    3290           0 :         return CMD_SUCCESS;
    3291             : }
    3292             : 
    3293           0 : DEFUN (no_vtysh_integrated_config,
    3294             :        no_vtysh_integrated_config_cmd,
    3295             :        "no service integrated-vtysh-config",
    3296             :        NO_STR
    3297             :        "Set up miscellaneous service\n"
    3298             :        "Write configuration into integrated file\n")
    3299             : {
    3300           0 :         vtysh_write_integrated = WRITE_INTEGRATED_NO;
    3301           0 :         return CMD_SUCCESS;
    3302             : }
    3303             : 
    3304           0 : static void backup_config_file(const char *fbackup)
    3305             : {
    3306           0 :         char *integrate_sav = NULL;
    3307             : 
    3308           0 :         size_t integrate_sav_sz = strlen(fbackup) + strlen(CONF_BACKUP_EXT) + 1;
    3309           0 :         integrate_sav = malloc(integrate_sav_sz);
    3310           0 :         strlcpy(integrate_sav, fbackup, integrate_sav_sz);
    3311           0 :         strlcat(integrate_sav, CONF_BACKUP_EXT, integrate_sav_sz);
    3312             : 
    3313             :         /* Move current configuration file to backup config file. */
    3314           0 :         if (unlink(integrate_sav) != 0 && errno != ENOENT)
    3315           0 :                 vty_out(vty, "Unlink failed for %s: %s\n", integrate_sav,
    3316             :                         strerror(errno));
    3317           0 :         if (rename(fbackup, integrate_sav) != 0 && errno != ENOENT)
    3318           0 :                 vty_out(vty, "Error renaming %s to %s: %s\n", fbackup,
    3319             :                         integrate_sav, strerror(errno));
    3320           0 :         free(integrate_sav);
    3321           0 : }
    3322             : 
    3323           0 : int vtysh_write_config_integrated(void)
    3324             : {
    3325           0 :         unsigned int i;
    3326           0 :         char line[] = "do write terminal";
    3327           0 :         FILE *fp;
    3328           0 :         int fd;
    3329             : #ifdef FRR_USER
    3330           0 :         struct passwd *pwentry;
    3331             : #endif
    3332             : #ifdef FRR_GROUP
    3333           0 :         struct group *grentry;
    3334             : #endif
    3335           0 :         uid_t uid = -1;
    3336           0 :         gid_t gid = -1;
    3337           0 :         struct stat st;
    3338           0 :         int err = 0;
    3339             : 
    3340           0 :         vty_out(vty, "Building Configuration...\n");
    3341             : 
    3342           0 :         backup_config_file(frr_config);
    3343           0 :         fp = fopen(frr_config, "w");
    3344           0 :         if (fp == NULL) {
    3345           0 :                 vty_out(vty,
    3346             :                         "%% Error: failed to open configuration file %s: %s\n",
    3347           0 :                         frr_config, safe_strerror(errno));
    3348           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3349             :         }
    3350           0 :         fd = fileno(fp);
    3351             : 
    3352           0 :         for (i = 0; i < array_size(vtysh_client); i++)
    3353           0 :                 vtysh_client_config(&vtysh_client[i], line);
    3354             : 
    3355           0 :         vtysh_config_write();
    3356           0 :         vty->of_saved = vty->of;
    3357           0 :         vty->of = fp;
    3358           0 :         vtysh_config_dump();
    3359           0 :         vty->of = vty->of_saved;
    3360             : 
    3361           0 :         if (fchmod(fd, CONFIGFILE_MASK) != 0) {
    3362           0 :                 printf("%% Warning: can't chmod configuration file %s: %s\n",
    3363           0 :                        frr_config, safe_strerror(errno));
    3364           0 :                 err++;
    3365             :         }
    3366             : 
    3367             : #ifdef FRR_USER
    3368           0 :         pwentry = getpwnam(FRR_USER);
    3369           0 :         if (pwentry)
    3370           0 :                 uid = pwentry->pw_uid;
    3371             :         else {
    3372           0 :                 printf("%% Warning: could not look up user \"%s\"\n", FRR_USER);
    3373           0 :                 err++;
    3374             :         }
    3375             : #endif
    3376             : #ifdef FRR_GROUP
    3377           0 :         grentry = getgrnam(FRR_GROUP);
    3378           0 :         if (grentry)
    3379           0 :                 gid = grentry->gr_gid;
    3380             :         else {
    3381           0 :                 printf("%% Warning: could not look up group \"%s\"\n",
    3382             :                        FRR_GROUP);
    3383           0 :                 err++;
    3384             :         }
    3385             : #endif
    3386             : 
    3387           0 :         if (!fstat(fd, &st)) {
    3388           0 :                 if (st.st_uid == uid)
    3389           0 :                         uid = -1;
    3390           0 :                 if (st.st_gid == gid)
    3391           0 :                         gid = -1;
    3392           0 :                 if ((uid != (uid_t)-1 || gid != (gid_t)-1)
    3393           0 :                     && fchown(fd, uid, gid)) {
    3394           0 :                         printf("%% Warning: can't chown configuration file %s: %s\n",
    3395           0 :                                frr_config, safe_strerror(errno));
    3396           0 :                         err++;
    3397             :                 }
    3398             :         } else {
    3399           0 :                 printf("%% Warning: stat() failed on %s: %s\n", frr_config,
    3400           0 :                        safe_strerror(errno));
    3401           0 :                 err++;
    3402             :         }
    3403             : 
    3404           0 :         if (fflush(fp) != 0) {
    3405           0 :                 printf("%% Warning: fflush() failed on %s: %s\n", frr_config,
    3406           0 :                        safe_strerror(errno));
    3407           0 :                 err++;
    3408             :         }
    3409             : 
    3410           0 :         if (fsync(fd) < 0) {
    3411           0 :                 printf("%% Warning: fsync() failed on %s: %s\n", frr_config,
    3412           0 :                        safe_strerror(errno));
    3413           0 :                 err++;
    3414             :         }
    3415             : 
    3416           0 :         fclose(fp);
    3417             : 
    3418           0 :         printf("Integrated configuration saved to %s\n", frr_config);
    3419           0 :         if (err)
    3420             :                 return CMD_WARNING;
    3421             : 
    3422           0 :         printf("[OK]\n");
    3423           0 :         return CMD_SUCCESS;
    3424             : }
    3425             : 
    3426           2 : DEFUN_HIDDEN(start_config, start_config_cmd, "XFRR_start_configuration",
    3427             :              "The Beginning of Configuration\n")
    3428             : {
    3429           2 :         unsigned int i;
    3430           2 :         char line[] = "XFRR_start_configuration";
    3431             : 
    3432          44 :         for (i = 0; i < array_size(vtysh_client); i++)
    3433          42 :                 vtysh_client_execute(&vtysh_client[i], line);
    3434             : 
    3435           2 :         return CMD_SUCCESS;
    3436             : }
    3437             : 
    3438           2 : DEFUN_HIDDEN(end_config, end_config_cmd, "XFRR_end_configuration",
    3439             :              "The End of Configuration\n")
    3440             : {
    3441           2 :         unsigned int i;
    3442           2 :         char line[] = "XFRR_end_configuration";
    3443             : 
    3444          44 :         for (i = 0; i < array_size(vtysh_client); i++)
    3445          42 :                 vtysh_client_execute(&vtysh_client[i], line);
    3446             : 
    3447           2 :         return CMD_SUCCESS;
    3448             : }
    3449             : 
    3450           0 : static bool want_config_integrated(void)
    3451             : {
    3452           0 :         struct stat s;
    3453             : 
    3454           0 :         switch (vtysh_write_integrated) {
    3455           0 :         case WRITE_INTEGRATED_UNSPECIFIED:
    3456           0 :                 if (stat(frr_config, &s) && errno == ENOENT)
    3457             :                         return false;
    3458             :                 return true;
    3459             :         case WRITE_INTEGRATED_NO:
    3460             :                 return false;
    3461             :         case WRITE_INTEGRATED_YES:
    3462             :                 return true;
    3463             :         }
    3464             :         return true;
    3465             : }
    3466             : 
    3467           0 : DEFUN (vtysh_write_memory,
    3468             :        vtysh_write_memory_cmd,
    3469             :        "write [<memory|file>]",
    3470             :        "Write running configuration to memory, network, or terminal\n"
    3471             :        "Write configuration to the file (same as write file)\n"
    3472             :        "Write configuration to the file (same as write memory)\n")
    3473             : {
    3474           0 :         int ret = CMD_SUCCESS;
    3475           0 :         char line[] = "do write memory";
    3476           0 :         unsigned int i;
    3477             : 
    3478           0 :         vty_out(vty, "Note: this version of vtysh never writes vtysh.conf\n");
    3479             : 
    3480             :         /* If integrated frr.conf explicitly set. */
    3481           0 :         if (want_config_integrated()) {
    3482           0 :                 ret = CMD_WARNING_CONFIG_FAILED;
    3483             : 
    3484             :                 /* first attempt to use watchfrr if it's available */
    3485           0 :                 bool used_watchfrr = false;
    3486             : 
    3487           0 :                 for (i = 0; i < array_size(vtysh_client); i++)
    3488           0 :                         if (vtysh_client[i].flag == VTYSH_WATCHFRR)
    3489             :                                 break;
    3490           0 :                 if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1) {
    3491           0 :                         used_watchfrr = true;
    3492           0 :                         ret = vtysh_client_execute(&vtysh_client[i],
    3493             :                                                    "do write integrated");
    3494             :                 }
    3495             : 
    3496             :                 /*
    3497             :                  * If we didn't use watchfrr, fallback to writing the config
    3498             :                  * ourselves
    3499             :                  */
    3500           0 :                 if (!used_watchfrr) {
    3501           0 :                         printf("\nWarning: attempting direct configuration write without watchfrr.\nFile permissions and ownership may be incorrect, or write may fail.\n\n");
    3502           0 :                         ret = vtysh_write_config_integrated();
    3503             :                 }
    3504           0 :                 return ret;
    3505             :         }
    3506             : 
    3507           0 :         vty_out(vty, "Building Configuration...\n");
    3508             : 
    3509           0 :         for (i = 0; i < array_size(vtysh_client); i++)
    3510           0 :                 ret = vtysh_client_execute(&vtysh_client[i], line);
    3511             : 
    3512             :         return ret;
    3513             : }
    3514             : 
    3515           0 : DEFUN (vtysh_copy_running_config,
    3516             :        vtysh_copy_running_config_cmd,
    3517             :        "copy running-config startup-config",
    3518             :        "Copy from one file to another\n"
    3519             :        "Copy from current system configuration\n"
    3520             :        "Copy to startup configuration\n")
    3521             : {
    3522           0 :         return vtysh_write_memory(self, vty, argc, argv);
    3523             : }
    3524             : 
    3525           0 : DEFUN (vtysh_copy_to_running,
    3526             :        vtysh_copy_to_running_cmd,
    3527             :        "copy FILENAME running-config",
    3528             :        "Apply a configuration file\n"
    3529             :        "Configuration file to read\n"
    3530             :        "Apply to current configuration\n")
    3531             : {
    3532           0 :         int ret;
    3533           0 :         const char *fname = argv[1]->arg;
    3534             : 
    3535           0 :         ret = vtysh_read_config(fname, true);
    3536             : 
    3537             :         /* Return to enable mode - the 'read_config' api leaves us up a level */
    3538           0 :         vtysh_execute_no_pager("enable");
    3539             : 
    3540           0 :         return ret;
    3541             : }
    3542             : 
    3543           0 : DEFUN (vtysh_terminal_paginate,
    3544             :        vtysh_terminal_paginate_cmd,
    3545             :        "[no] terminal paginate",
    3546             :        NO_STR
    3547             :        "Set terminal line parameters\n"
    3548             :        "Use pager for output scrolling\n")
    3549             : {
    3550           0 :         free(vtysh_pager_name);
    3551           0 :         vtysh_pager_name = NULL;
    3552             : 
    3553           0 :         if (strcmp(argv[0]->text, "no"))
    3554           0 :                 vtysh_pager_envdef(true);
    3555           0 :         return CMD_SUCCESS;
    3556             : }
    3557             : 
    3558           0 : DEFUN (vtysh_terminal_length,
    3559             :        vtysh_terminal_length_cmd,
    3560             :        "[no] terminal length (0-4294967295)",
    3561             :        NO_STR
    3562             :        "Set terminal line parameters\n"
    3563             :        "Set number of lines on a screen\n"
    3564             :        "Number of lines on screen (0 for no pausing, nonzero to use pager)\n")
    3565             : {
    3566           0 :         int idx_number = 2;
    3567           0 :         unsigned long lines;
    3568             : 
    3569           0 :         free(vtysh_pager_name);
    3570           0 :         vtysh_pager_name = NULL;
    3571             : 
    3572           0 :         if (!strcmp(argv[0]->text, "no") || !strcmp(argv[1]->text, "no")) {
    3573             :                 /* "terminal no length" = use VTYSH_PAGER */
    3574           0 :                 vtysh_pager_envdef(true);
    3575           0 :                 return CMD_SUCCESS;
    3576             :         }
    3577             : 
    3578           0 :         lines = strtoul(argv[idx_number]->arg, NULL, 10);
    3579           0 :         if (lines != 0) {
    3580           0 :                 vty_out(vty,
    3581             :                         "%% The \"terminal length\" command is deprecated and its value is ignored.\n"
    3582             :                         "%% Please use \"terminal paginate\" instead with OS TTY length handling.\n");
    3583           0 :                 vtysh_pager_envdef(true);
    3584             :         }
    3585             : 
    3586             :         return CMD_SUCCESS;
    3587             : }
    3588             : 
    3589             : ALIAS_DEPRECATED(vtysh_terminal_length,
    3590             :        vtysh_terminal_no_length_cmd,
    3591             :        "terminal no length",
    3592             :        "Set terminal line parameters\n"
    3593             :        NO_STR
    3594             :        "Set number of lines on a screen\n")
    3595             : 
    3596           0 : DEFUN (vtysh_show_daemons,
    3597             :        vtysh_show_daemons_cmd,
    3598             :        "show daemons",
    3599             :        SHOW_STR
    3600             :        "Show list of running daemons\n")
    3601             : {
    3602           0 :         unsigned int i;
    3603             : 
    3604           0 :         for (i = 0; i < array_size(vtysh_client); i++)
    3605           0 :                 if (vtysh_client[i].fd >= 0)
    3606           0 :                         vty_out(vty, " %s", vtysh_client[i].name);
    3607           0 :         vty_out(vty, "\n");
    3608             : 
    3609           0 :         return CMD_SUCCESS;
    3610             : }
    3611             : 
    3612             : struct visual_prio {
    3613             :         /* 4 characters for nice alignment */
    3614             :         const char *label;
    3615             : 
    3616             :         int c256_background;
    3617             :         int c256_formatarg;
    3618             : };
    3619             : 
    3620             : /* clang-format off */
    3621             : struct visual_prio visual_prios[] = {
    3622             :         [LOG_EMERG] = {
    3623             :                 .label = "\e[31;1mEMRG",
    3624             :                 .c256_background = 53,
    3625             :                 .c256_formatarg = 225,
    3626             :         },
    3627             :         [LOG_ALERT] = {
    3628             :                 .label = "\e[31;1mALRT",
    3629             :                 .c256_background = 53,
    3630             :                 .c256_formatarg = 225,
    3631             :         },
    3632             :         [LOG_CRIT] = {
    3633             :                 .label = "\e[31;1mCRIT",
    3634             :                 .c256_background = 53,
    3635             :                 .c256_formatarg = 225,
    3636             :         },
    3637             :         [LOG_ERR] = {
    3638             :                 .label = "\e[38;5;202mERR!",
    3639             :                 .c256_background = 52,
    3640             :                 .c256_formatarg = 224,
    3641             :         },
    3642             :         [LOG_WARNING] = {
    3643             :                 .label = "\e[38;5;222mWARN",
    3644             :                 .c256_background = 58,
    3645             :                 .c256_formatarg = 230,
    3646             :         },
    3647             :         [LOG_NOTICE] = {
    3648             :                 .label = "NTFY",
    3649             :                 .c256_background = 234,
    3650             :                 .c256_formatarg = 195,
    3651             :         },
    3652             :         [LOG_INFO] = {
    3653             :                 .label = "\e[38;5;192mINFO",
    3654             :                 .c256_background = 236,
    3655             :                 .c256_formatarg = 195,
    3656             :         },
    3657             :         [LOG_DEBUG] = {
    3658             :                 .label = "\e[38;5;116mDEBG",
    3659             :                 .c256_background = 238,
    3660             :                 .c256_formatarg = 195,
    3661             :         },
    3662             : };
    3663             : /* clang-format on */
    3664             : 
    3665           0 : static void vtysh_log_print(struct vtysh_client *vclient,
    3666             :                             struct zlog_live_hdr *hdr, const char *text)
    3667             : {
    3668           0 :         size_t textlen = hdr->textlen, textpos = 0;
    3669           0 :         time_t ts = hdr->ts_sec;
    3670           0 :         struct visual_prio *vis;
    3671           0 :         struct tm tm;
    3672           0 :         char ts_buf[32];
    3673             : 
    3674           0 :         if (hdr->prio >= array_size(visual_prios))
    3675             :                 vis = &visual_prios[LOG_CRIT];
    3676             :         else
    3677           0 :                 vis = &visual_prios[hdr->prio];
    3678             : 
    3679           0 :         localtime_r(&ts, &tm);
    3680           0 :         strftime(ts_buf, sizeof(ts_buf), "%Y-%m-%d %H:%M:%S", &tm);
    3681             : 
    3682           0 :         if (!stderr_tty) {
    3683           0 :                 const char *label = vis->label + strlen(vis->label) - 4;
    3684             : 
    3685           0 :                 fprintf(stderr, "%s.%03u [%s] %s: %.*s\n", ts_buf,
    3686           0 :                         hdr->ts_nsec / 1000000U, label, vclient->name,
    3687             :                         (int)textlen, text);
    3688           0 :                 return;
    3689             :         }
    3690             : 
    3691           0 :         fprintf(stderr,
    3692             :                 "\e[48;5;%dm\e[38;5;247m%s.%03u [%s\e[38;5;247m] \e[38;5;255m%s\e[38;5;247m: \e[38;5;251m",
    3693           0 :                 vis->c256_background, ts_buf, hdr->ts_nsec / 1000000U,
    3694             :                 vis->label, vclient->name);
    3695             : 
    3696           0 :         for (size_t fmtpos = 0; fmtpos < hdr->n_argpos; fmtpos++) {
    3697           0 :                 struct fmt_outpos *fmt = &hdr->argpos[fmtpos];
    3698             : 
    3699           0 :                 if (fmt->off_start < textpos || fmt->off_end < fmt->off_start ||
    3700             :                     fmt->off_end > textlen)
    3701           0 :                         continue;
    3702             : 
    3703           0 :                 while (fmt->off_end > fmt->off_start &&
    3704           0 :                        text[fmt->off_end - 1] == ' ')
    3705           0 :                         fmt->off_end--;
    3706             : 
    3707           0 :                 fprintf(stderr, "%.*s\e[38;5;%dm%.*s\e[38;5;251m",
    3708           0 :                         (int)(fmt->off_start - textpos), text + textpos,
    3709             :                         vis->c256_formatarg,
    3710           0 :                         (int)(fmt->off_end - fmt->off_start),
    3711             :                         text + fmt->off_start);
    3712           0 :                 textpos = fmt->off_end;
    3713             :         }
    3714           0 :         fprintf(stderr, "%.*s\033[K\033[m\n", (int)(textlen - textpos),
    3715             :                 text + textpos);
    3716             : }
    3717             : 
    3718           0 : static void vtysh_log_read(struct thread *thread)
    3719             : {
    3720           0 :         struct vtysh_client *vclient = THREAD_ARG(thread);
    3721           0 :         struct {
    3722             :                 struct zlog_live_hdr hdr;
    3723             :                 char text[4096];
    3724             :         } buf;
    3725           0 :         const char *text;
    3726           0 :         ssize_t ret;
    3727             : 
    3728           0 :         thread_add_read(master, vtysh_log_read, vclient, vclient->log_fd,
    3729             :                         &vclient->log_reader);
    3730             : 
    3731           0 :         ret = recv(vclient->log_fd, &buf, sizeof(buf), 0);
    3732             : 
    3733           0 :         if (ret < 0 && ERRNO_IO_RETRY(errno))
    3734             :                 return;
    3735             : 
    3736           0 :         if (stderr_stdout_same) {
    3737             : #ifdef HAVE_RL_CLEAR_VISIBLE_LINE
    3738           0 :                 rl_clear_visible_line();
    3739             : #else
    3740             :                 puts("\r");
    3741             : #endif
    3742           0 :                 fflush(stdout);
    3743             :         }
    3744             : 
    3745           0 :         if (ret <= 0) {
    3746           0 :                 struct timespec ts;
    3747             : 
    3748           0 :                 buf.text[0] = '\0'; /* coverity */
    3749             : 
    3750           0 :                 if (ret != 0)
    3751           0 :                         snprintfrr(buf.text, sizeof(buf.text),
    3752             :                                    "log monitor connection error: %m");
    3753             :                 else
    3754           0 :                         snprintfrr(
    3755             :                                 buf.text, sizeof(buf.text),
    3756             :                                 "log monitor connection closed unexpectedly");
    3757           0 :                 buf.hdr.textlen = strlen(buf.text);
    3758             : 
    3759           0 :                 THREAD_OFF(vclient->log_reader);
    3760           0 :                 close(vclient->log_fd);
    3761           0 :                 vclient->log_fd = -1;
    3762             : 
    3763           0 :                 clock_gettime(CLOCK_REALTIME, &ts);
    3764           0 :                 buf.hdr.ts_sec = ts.tv_sec;
    3765           0 :                 buf.hdr.ts_nsec = ts.tv_nsec;
    3766           0 :                 buf.hdr.prio = LOG_ERR;
    3767           0 :                 buf.hdr.flags = 0;
    3768           0 :                 buf.hdr.texthdrlen = 0;
    3769           0 :                 buf.hdr.n_argpos = 0;
    3770             :         } else {
    3771           0 :                 int32_t lost_msgs = buf.hdr.lost_msgs - vclient->lost_msgs;
    3772             : 
    3773           0 :                 if (lost_msgs > 0) {
    3774           0 :                         vclient->lost_msgs = buf.hdr.lost_msgs;
    3775           0 :                         fprintf(stderr,
    3776             :                                 "%d log messages from %s lost (vtysh reading too slowly)\n",
    3777             :                                 lost_msgs, vclient->name);
    3778             :                 }
    3779             :         }
    3780             : 
    3781           0 :         text = buf.text + sizeof(buf.hdr.argpos[0]) * buf.hdr.n_argpos;
    3782           0 :         vtysh_log_print(vclient, &buf.hdr, text);
    3783             : 
    3784           0 :         if (stderr_stdout_same)
    3785           0 :                 rl_forced_update_display();
    3786             : 
    3787             :         return;
    3788             : }
    3789             : 
    3790             : #ifdef CLIPPY
    3791             : /* clippy/clidef can't process the DEFPY below without some value for this */
    3792             : #define DAEMONS_LIST "daemon"
    3793             : #endif
    3794             : 
    3795           0 : DEFPY (vtysh_terminal_monitor,
    3796             :        vtysh_terminal_monitor_cmd,
    3797             :        "terminal monitor ["DAEMONS_LIST"]$daemon",
    3798             :        "Set terminal line parameters\n"
    3799             :        "Receive log messages to active VTY session\n"
    3800             :        DAEMONS_STR)
    3801             : {
    3802           0 :         static const char line[] = "terminal monitor";
    3803           0 :         int ret_all = CMD_SUCCESS, ret, fd;
    3804           0 :         size_t i, ok = 0;
    3805             : 
    3806           0 :         for (i = 0; i < array_size(vtysh_client); i++) {
    3807           0 :                 struct vtysh_client *vclient = &vtysh_client[i];
    3808             : 
    3809           0 :                 if (daemon && strcmp(vclient->name, daemon))
    3810           0 :                         continue;
    3811             : 
    3812           0 :                 for (; vclient; vclient = vclient->next) {
    3813           0 :                         if (vclient->log_fd != -1) {
    3814           0 :                                 vty_out(vty, "%% %s: already monitoring logs\n",
    3815             :                                         vclient->name);
    3816           0 :                                 ok++;
    3817           0 :                                 continue;
    3818             :                         }
    3819             : 
    3820           0 :                         fd = -1;
    3821           0 :                         ret = vtysh_client_run(vclient, line, NULL, NULL, &fd);
    3822           0 :                         if (fd != -1) {
    3823           0 :                                 set_nonblocking(fd);
    3824           0 :                                 vclient->log_fd = fd;
    3825           0 :                                 thread_add_read(master, vtysh_log_read, vclient,
    3826             :                                                 vclient->log_fd,
    3827             :                                                 &vclient->log_reader);
    3828             :                         }
    3829           0 :                         if (ret != CMD_SUCCESS) {
    3830           0 :                                 vty_out(vty, "%% failed to enable logs on %s\n",
    3831             :                                         vclient->name);
    3832           0 :                                 ret_all = CMD_WARNING;
    3833             :                         } else
    3834           0 :                                 ok++;
    3835             :                 }
    3836             :         }
    3837             : 
    3838           0 :         if (!ok && ret_all == CMD_SUCCESS) {
    3839           0 :                 vty_out(vty,
    3840             :                         "%% command had no effect, relevant daemons not connected?\n");
    3841           0 :                 ret_all = CMD_WARNING;
    3842             :         }
    3843           0 :         return ret_all;
    3844             : }
    3845             : 
    3846           0 : DEFPY (no_vtysh_terminal_monitor,
    3847             :        no_vtysh_terminal_monitor_cmd,
    3848             :        "no terminal monitor ["DAEMONS_LIST"]$daemon",
    3849             :        NO_STR
    3850             :        "Set terminal line parameters\n"
    3851             :        "Receive log messages to active VTY session\n"
    3852             :        DAEMONS_STR)
    3853             : {
    3854           0 :         static const char line[] = "no terminal monitor";
    3855           0 :         int ret_all = CMD_SUCCESS, ret;
    3856           0 :         size_t i, ok = 0;
    3857             : 
    3858           0 :         for (i = 0; i < array_size(vtysh_client); i++) {
    3859           0 :                 struct vtysh_client *vclient = &vtysh_client[i];
    3860             : 
    3861           0 :                 if (daemon && strcmp(vclient->name, daemon))
    3862           0 :                         continue;
    3863             : 
    3864           0 :                 for (; vclient; vclient = vclient->next) {
    3865             :                         /* run this even if log_fd == -1, in case something
    3866             :                          * got desync'd
    3867             :                          */
    3868           0 :                         ret = vtysh_client_run(vclient, line, NULL, NULL, NULL);
    3869           0 :                         if (ret != CMD_SUCCESS) {
    3870           0 :                                 vty_out(vty,
    3871             :                                         "%% failed to disable logs on %s\n",
    3872             :                                         vclient->name);
    3873           0 :                                 ret_all = CMD_WARNING;
    3874             :                         } else
    3875           0 :                                 ok++;
    3876             : 
    3877             :                         /* with this being a datagram socket, we can't expect
    3878             :                          * a close notification...
    3879             :                          */
    3880           0 :                         if (vclient->log_fd != -1) {
    3881           0 :                                 THREAD_OFF(vclient->log_reader);
    3882             : 
    3883           0 :                                 close(vclient->log_fd);
    3884           0 :                                 vclient->log_fd = -1;
    3885             :                         }
    3886             :                 }
    3887             :         }
    3888             : 
    3889           0 :         if (!ok && ret_all == CMD_SUCCESS) {
    3890           0 :                 vty_out(vty,
    3891             :                         "%% command had no effect, relevant daemons not connected?\n");
    3892           0 :                 ret_all = CMD_WARNING;
    3893             :         }
    3894           0 :         return ret_all;
    3895             : }
    3896             : 
    3897             : 
    3898             : /* Execute command in child process. */
    3899           0 : static void execute_command(const char *command, int argc, const char *arg1,
    3900             :                             const char *arg2)
    3901             : {
    3902           0 :         pid_t pid;
    3903           0 :         int status;
    3904             : 
    3905             :         /* Call fork(). */
    3906           0 :         pid = fork();
    3907             : 
    3908           0 :         if (pid < 0) {
    3909             :                 /* Failure of fork(). */
    3910           0 :                 fprintf(stderr, "Can't fork: %s\n", safe_strerror(errno));
    3911           0 :                 exit(1);
    3912           0 :         } else if (pid == 0) {
    3913             :                 /* This is child process. */
    3914           0 :                 switch (argc) {
    3915           0 :                 case 0:
    3916           0 :                         execlp(command, command, (const char *)NULL);
    3917           0 :                         break;
    3918           0 :                 case 1:
    3919           0 :                         execlp(command, command, arg1, (const char *)NULL);
    3920           0 :                         break;
    3921           0 :                 case 2:
    3922           0 :                         execlp(command, command, arg1, arg2,
    3923             :                                (const char *)NULL);
    3924           0 :                         break;
    3925             :                 }
    3926             : 
    3927             :                 /* When execlp suceed, this part is not executed. */
    3928           0 :                 fprintf(stderr, "Can't execute %s: %s\n", command,
    3929           0 :                         safe_strerror(errno));
    3930           0 :                 exit(1);
    3931             :         } else {
    3932             :                 /* This is parent. */
    3933           0 :                 execute_flag = 1;
    3934           0 :                 wait4(pid, &status, 0, NULL);
    3935           0 :                 execute_flag = 0;
    3936             :         }
    3937           0 : }
    3938             : 
    3939           0 : DEFUN (vtysh_ping,
    3940             :        vtysh_ping_cmd,
    3941             :        "ping WORD",
    3942             :        "Send echo messages\n"
    3943             :        "Ping destination address or hostname\n")
    3944             : {
    3945           0 :         int idx = 1;
    3946             : 
    3947           0 :         argv_find(argv, argc, "WORD", &idx);
    3948           0 :         execute_command("ping", 1, argv[idx]->arg, NULL);
    3949           0 :         return CMD_SUCCESS;
    3950             : }
    3951             : 
    3952           0 : DEFUN(vtysh_motd, vtysh_motd_cmd, "show motd", SHOW_STR "Show motd\n")
    3953             : {
    3954           0 :         vty_hello(vty);
    3955           0 :         return CMD_SUCCESS;
    3956             : }
    3957             : 
    3958             : ALIAS(vtysh_ping, vtysh_ping_ip_cmd, "ping ip WORD",
    3959             :       "Send echo messages\n"
    3960             :       "IP echo\n"
    3961             :       "Ping destination address or hostname\n")
    3962             : 
    3963           0 : DEFUN (vtysh_traceroute,
    3964             :        vtysh_traceroute_cmd,
    3965             :        "traceroute WORD",
    3966             :        "Trace route to destination\n"
    3967             :        "Trace route to destination address or hostname\n")
    3968             : {
    3969           0 :         int idx = 1;
    3970             : 
    3971           0 :         argv_find(argv, argc, "WORD", &idx);
    3972           0 :         execute_command("traceroute", 1, argv[idx]->arg, NULL);
    3973           0 :         return CMD_SUCCESS;
    3974             : }
    3975             : 
    3976             : ALIAS(vtysh_traceroute, vtysh_traceroute_ip_cmd, "traceroute ip WORD",
    3977             :       "Trace route to destination\n"
    3978             :       "IP trace\n"
    3979             :       "Trace route to destination address or hostname\n")
    3980             : 
    3981           0 : DEFUN (vtysh_mtrace,
    3982             :        vtysh_mtrace_cmd,
    3983             :        "mtrace WORD [WORD]",
    3984             :        "Multicast trace route to multicast source\n"
    3985             :        "Multicast trace route to multicast source address\n"
    3986             :        "Multicast trace route for multicast group address\n")
    3987             : {
    3988           0 :         if (argc == 2)
    3989           0 :                 execute_command("mtracebis", 1, argv[1]->arg, NULL);
    3990             :         else
    3991           0 :                 execute_command("mtracebis", 2, argv[1]->arg, argv[2]->arg);
    3992           0 :         return CMD_SUCCESS;
    3993             : }
    3994             : 
    3995           0 : DEFUN (vtysh_ping6,
    3996             :        vtysh_ping6_cmd,
    3997             :        "ping ipv6 WORD",
    3998             :        "Send echo messages\n"
    3999             :        "IPv6 echo\n"
    4000             :        "Ping destination address or hostname\n")
    4001             : {
    4002           0 :         execute_command("ping6", 1, argv[2]->arg, NULL);
    4003           0 :         return CMD_SUCCESS;
    4004             : }
    4005             : 
    4006           0 : DEFUN (vtysh_traceroute6,
    4007             :        vtysh_traceroute6_cmd,
    4008             :        "traceroute ipv6 WORD",
    4009             :        "Trace route to destination\n"
    4010             :        "IPv6 trace\n"
    4011             :        "Trace route to destination address or hostname\n")
    4012             : {
    4013           0 :         execute_command("traceroute6", 1, argv[2]->arg, NULL);
    4014           0 :         return CMD_SUCCESS;
    4015             : }
    4016             : 
    4017             : #if CONFDATE > 20240201
    4018             : CPP_NOTICE("Remove HAVE_SHELL_ACCESS and it's documentation");
    4019             : #endif
    4020             : #if defined(HAVE_SHELL_ACCESS)
    4021             : DEFUN (vtysh_telnet,
    4022             :        vtysh_telnet_cmd,
    4023             :        "telnet WORD",
    4024             :        "Open a telnet connection\n"
    4025             :        "IP address or hostname of a remote system\n")
    4026             : {
    4027             :         execute_command("telnet", 1, argv[1]->arg, NULL);
    4028             :         return CMD_SUCCESS;
    4029             : }
    4030             : 
    4031             : DEFUN (vtysh_telnet_port,
    4032             :        vtysh_telnet_port_cmd,
    4033             :        "telnet WORD PORT",
    4034             :        "Open a telnet connection\n"
    4035             :        "IP address or hostname of a remote system\n"
    4036             :        "TCP Port number\n")
    4037             : {
    4038             :         execute_command("telnet", 2, argv[1]->arg, argv[2]->arg);
    4039             :         return CMD_SUCCESS;
    4040             : }
    4041             : 
    4042             : DEFUN (vtysh_ssh,
    4043             :        vtysh_ssh_cmd,
    4044             :        "ssh WORD",
    4045             :        "Open an ssh connection\n"
    4046             :        "[user@]host\n")
    4047             : {
    4048             :         execute_command("ssh", 1, argv[1]->arg, NULL);
    4049             :         return CMD_SUCCESS;
    4050             : }
    4051             : 
    4052             : DEFUN (vtysh_start_shell,
    4053             :        vtysh_start_shell_cmd,
    4054             :        "start-shell",
    4055             :        "Start UNIX shell\n")
    4056             : {
    4057             :         execute_command("sh", 0, NULL, NULL);
    4058             :         return CMD_SUCCESS;
    4059             : }
    4060             : 
    4061             : DEFUN (vtysh_start_bash,
    4062             :        vtysh_start_bash_cmd,
    4063             :        "start-shell bash",
    4064             :        "Start UNIX shell\n"
    4065             :        "Start bash\n")
    4066             : {
    4067             :         execute_command("bash", 0, NULL, NULL);
    4068             :         return CMD_SUCCESS;
    4069             : }
    4070             : 
    4071             : DEFUN (vtysh_start_zsh,
    4072             :        vtysh_start_zsh_cmd,
    4073             :        "start-shell zsh",
    4074             :        "Start UNIX shell\n"
    4075             :        "Start Z shell\n")
    4076             : {
    4077             :         execute_command("zsh", 0, NULL, NULL);
    4078             :         return CMD_SUCCESS;
    4079             : }
    4080             : #endif
    4081             : 
    4082           0 : DEFUN (config_list,
    4083             :        config_list_cmd,
    4084             :        "list [permutations]",
    4085             :        "Print command list\n"
    4086             :        "Print all possible command permutations\n")
    4087             : {
    4088           0 :         return cmd_list_cmds(vty, argc == 2);
    4089             : }
    4090             : 
    4091           0 : DEFUN (vtysh_output_file,
    4092             :        vtysh_output_file_cmd,
    4093             :        "output file FILE",
    4094             :        "Direct vtysh output to file\n"
    4095             :        "Direct vtysh output to file\n"
    4096             :        "Path to dump output to\n")
    4097             : {
    4098           0 :         const char *path = argv[argc - 1]->arg;
    4099           0 :         vty->of = fopen(path, "a");
    4100           0 :         if (!vty->of) {
    4101           0 :                 vty_out(vty, "Failed to open file '%s': %s\n", path,
    4102           0 :                         safe_strerror(errno));
    4103           0 :                 vty->of = stdout;
    4104             :         }
    4105           0 :         return CMD_SUCCESS;
    4106             : }
    4107             : 
    4108           0 : DEFUN (no_vtysh_output_file,
    4109             :        no_vtysh_output_file_cmd,
    4110             :        "no output file [FILE]",
    4111             :        NO_STR
    4112             :        "Direct vtysh output to file\n"
    4113             :        "Direct vtysh output to file\n"
    4114             :        "Path to dump output to\n")
    4115             : {
    4116           0 :         if (vty->of != stdout) {
    4117           0 :                 fclose(vty->of);
    4118           0 :                 vty->of = stdout;
    4119             :         }
    4120           0 :         return CMD_SUCCESS;
    4121             : }
    4122             : 
    4123           0 : DEFUN(find,
    4124             :       find_cmd,
    4125             :       "find REGEX...",
    4126             :       "Find CLI command matching a regular expression\n"
    4127             :       "Search pattern (POSIX regex)\n")
    4128             : {
    4129           0 :         return cmd_find_cmds(vty, argv, argc);
    4130             : }
    4131             : 
    4132           0 : DEFUN_HIDDEN(show_cli_graph_vtysh,
    4133             :              show_cli_graph_vtysh_cmd,
    4134             :              "show cli graph",
    4135             :              SHOW_STR
    4136             :              "CLI reflection\n"
    4137             :              "Dump current command space as DOT graph\n")
    4138             : {
    4139           0 :         struct cmd_node *cn = vector_slot(cmdvec, vty->node);
    4140           0 :         char *dot = cmd_graph_dump_dot(cn->cmdgraph);
    4141             : 
    4142           0 :         vty_out(vty, "%s\n", dot);
    4143           0 :         XFREE(MTYPE_TMP, dot);
    4144           0 :         return CMD_SUCCESS;
    4145             : }
    4146             : 
    4147          62 : static void vtysh_install_default(enum node_type node)
    4148             : {
    4149          62 :         _install_element(node, &config_list_cmd);
    4150          62 :         _install_element(node, &find_cmd);
    4151          62 :         _install_element(node, &show_cli_graph_vtysh_cmd);
    4152          62 :         _install_element(node, &vtysh_output_file_cmd);
    4153          62 :         _install_element(node, &no_vtysh_output_file_cmd);
    4154          62 : }
    4155             : 
    4156             : /* Making connection to protocol daemon. */
    4157           1 : static int vtysh_connect(struct vtysh_client *vclient)
    4158             : {
    4159           1 :         int ret;
    4160           1 :         int sock, len;
    4161           1 :         struct sockaddr_un addr;
    4162           1 :         struct stat s_stat;
    4163           1 :         const char *path;
    4164             : 
    4165           1 :         if (!vclient->path[0])
    4166           1 :                 snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty",
    4167             :                          vtydir, vclient->name);
    4168           1 :         path = vclient->path;
    4169             : 
    4170             :         /* Stat socket to see if we have permission to access it. */
    4171           1 :         ret = stat(path, &s_stat);
    4172           1 :         if (ret < 0 && errno != ENOENT) {
    4173           0 :                 fprintf(stderr, "vtysh_connect(%s): stat = %s\n", path,
    4174             :                         safe_strerror(errno));
    4175           0 :                 exit(1);
    4176             :         }
    4177             : 
    4178             :         if (ret >= 0) {
    4179           1 :                 if (!S_ISSOCK(s_stat.st_mode)) {
    4180           0 :                         fprintf(stderr, "vtysh_connect(%s): Not a socket\n",
    4181             :                                 path);
    4182           0 :                         exit(1);
    4183             :                 }
    4184             :         }
    4185             : 
    4186           1 :         sock = socket(AF_UNIX, SOCK_STREAM, 0);
    4187           1 :         if (sock < 0) {
    4188             : #ifdef DEBUG
    4189             :                 fprintf(stderr, "vtysh_connect(%s): socket = %s\n", path,
    4190             :                         safe_strerror(errno));
    4191             : #endif /* DEBUG */
    4192             :                 return -1;
    4193             :         }
    4194             : 
    4195           1 :         memset(&addr, 0, sizeof(addr));
    4196           1 :         addr.sun_family = AF_UNIX;
    4197           1 :         strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
    4198             : #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
    4199             :         len = addr.sun_len = SUN_LEN(&addr);
    4200             : #else
    4201           1 :         len = sizeof(addr.sun_family) + strlen(addr.sun_path);
    4202             : #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
    4203             : 
    4204           1 :         ret = connect(sock, (struct sockaddr *)&addr, len);
    4205           1 :         if (ret < 0) {
    4206             : #ifdef DEBUG
    4207             :                 fprintf(stderr, "vtysh_connect(%s): connect = %s\n", path,
    4208             :                         safe_strerror(errno));
    4209             : #endif /* DEBUG */
    4210           0 :                 close(sock);
    4211           0 :                 return -1;
    4212             :         }
    4213           1 :         vclient->fd = sock;
    4214             : 
    4215           1 :         return 0;
    4216             : }
    4217             : 
    4218           0 : static int vtysh_reconnect(struct vtysh_client *vclient)
    4219             : {
    4220           0 :         int ret;
    4221             : 
    4222           0 :         fprintf(stderr, "Warning: connecting to %s...", vclient->name);
    4223           0 :         ret = vtysh_connect(vclient);
    4224           0 :         if (ret < 0) {
    4225           0 :                 fprintf(stderr, "failed!\n");
    4226           0 :                 return ret;
    4227             :         }
    4228           0 :         fprintf(stderr, "success!\n");
    4229           0 :         if (vtysh_client_execute(vclient, "enable") < 0)
    4230             :                 return -1;
    4231           0 :         return vtysh_execute_no_pager("end");
    4232             : }
    4233             : 
    4234             : /* Return true if str ends with suffix, else return false */
    4235           0 : static int ends_with(const char *str, const char *suffix)
    4236             : {
    4237           0 :         if (!str || !suffix)
    4238             :                 return 0;
    4239           0 :         size_t lenstr = strlen(str);
    4240           0 :         size_t lensuffix = strlen(suffix);
    4241           0 :         if (lensuffix > lenstr)
    4242             :                 return 0;
    4243           0 :         return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
    4244             : }
    4245             : 
    4246           0 : static void vtysh_client_sorted_insert(struct vtysh_client *head_client,
    4247             :                                        struct vtysh_client *client)
    4248             : {
    4249           0 :         struct vtysh_client *prev_node, *current_node;
    4250             : 
    4251           0 :         prev_node = head_client;
    4252           0 :         current_node = head_client->next;
    4253           0 :         while (current_node) {
    4254           0 :                 if (strcmp(current_node->path, client->path) > 0)
    4255             :                         break;
    4256             : 
    4257           0 :                 prev_node = current_node;
    4258           0 :                 current_node = current_node->next;
    4259             :         }
    4260           0 :         client->next = current_node;
    4261           0 :         prev_node->next = client;
    4262           0 : }
    4263             : 
    4264             : #define MAXIMUM_INSTANCES 10
    4265             : 
    4266           1 : static void vtysh_update_all_instances(struct vtysh_client *head_client)
    4267             : {
    4268           1 :         struct vtysh_client *client;
    4269           1 :         DIR *dir;
    4270           1 :         struct dirent *file;
    4271           1 :         int n = 0;
    4272             : 
    4273           1 :         if (head_client->flag != VTYSH_OSPFD)
    4274             :                 return;
    4275             : 
    4276             :         /* ls vty_sock_dir and look for all files ending in .vty */
    4277           0 :         dir = opendir(vtydir);
    4278           0 :         if (dir) {
    4279           0 :                 while ((file = readdir(dir)) != NULL) {
    4280           0 :                         if (frrstr_startswith(file->d_name, "ospfd-")
    4281           0 :                             && ends_with(file->d_name, ".vty")) {
    4282           0 :                                 if (n == MAXIMUM_INSTANCES) {
    4283           0 :                                         fprintf(stderr,
    4284             :                                                 "Parsing %s, client limit(%d) reached!\n",
    4285             :                                                 vtydir, n);
    4286           0 :                                         break;
    4287             :                                 }
    4288           0 :                                 client = (struct vtysh_client *)malloc(
    4289             :                                         sizeof(struct vtysh_client));
    4290           0 :                                 client->fd = -1;
    4291           0 :                                 client->name = "ospfd";
    4292           0 :                                 client->flag = VTYSH_OSPFD;
    4293           0 :                                 snprintf(client->path, sizeof(client->path),
    4294             :                                          "%s/%s", vtydir, file->d_name);
    4295           0 :                                 client->next = NULL;
    4296           0 :                                 vtysh_client_sorted_insert(head_client, client);
    4297           0 :                                 n++;
    4298             :                         }
    4299             :                 }
    4300           0 :                 closedir(dir);
    4301             :         }
    4302             : }
    4303             : 
    4304           1 : static int vtysh_connect_all_instances(struct vtysh_client *head_client)
    4305             : {
    4306           1 :         struct vtysh_client *client;
    4307           1 :         int rc = 0;
    4308             : 
    4309           1 :         vtysh_update_all_instances(head_client);
    4310             : 
    4311           1 :         client = head_client->next;
    4312           1 :         while (client) {
    4313           0 :                 if (vtysh_connect(client) == 0)
    4314           0 :                         rc++;
    4315           0 :                 client = client->next;
    4316             :         }
    4317             : 
    4318           1 :         return rc;
    4319             : }
    4320             : 
    4321           1 : int vtysh_connect_all(const char *daemon_name)
    4322             : {
    4323           1 :         unsigned int i;
    4324           1 :         int rc = 0;
    4325           1 :         int matches = 0;
    4326             : 
    4327          22 :         for (i = 0; i < array_size(vtysh_client); i++) {
    4328          21 :                 if (!daemon_name
    4329          21 :                     || !strcmp(daemon_name, vtysh_client[i].name)) {
    4330           1 :                         matches++;
    4331           1 :                         if (vtysh_connect(&vtysh_client[i]) == 0)
    4332           1 :                                 rc++;
    4333             : 
    4334           1 :                         rc += vtysh_connect_all_instances(&vtysh_client[i]);
    4335             :                 }
    4336             :         }
    4337           1 :         if (!matches)
    4338           0 :                 fprintf(stderr, "Error: no daemons match name %s!\n",
    4339             :                         daemon_name);
    4340           1 :         return rc;
    4341             : }
    4342             : 
    4343             : /* To disable readline's filename completion. */
    4344           0 : static char *vtysh_completion_entry_function(const char *ignore,
    4345             :                                              int invoking_key)
    4346             : {
    4347           0 :         return NULL;
    4348             : }
    4349             : 
    4350           0 : void vtysh_readline_init(void)
    4351             : {
    4352             :         /* readline related settings. */
    4353           0 :         char *disable_bracketed_paste =
    4354           0 :                 XSTRDUP(MTYPE_TMP, "set enable-bracketed-paste off");
    4355             : 
    4356           0 :         rl_initialize();
    4357           0 :         rl_parse_and_bind(disable_bracketed_paste);
    4358           0 :         rl_bind_key('?', (rl_command_func_t *)vtysh_rl_describe);
    4359           0 :         rl_completion_entry_function = vtysh_completion_entry_function;
    4360           0 :         rl_attempted_completion_function = new_completion;
    4361             : 
    4362           0 :         XFREE(MTYPE_TMP, disable_bracketed_paste);
    4363           0 : }
    4364             : 
    4365           0 : char *vtysh_prompt(void)
    4366             : {
    4367           0 :         static char buf[512];
    4368             : 
    4369             : #pragma GCC diagnostic push
    4370             : #pragma GCC diagnostic ignored "-Wformat-nonliteral"
    4371             :         /* prompt formatting has a %s in the cmd_node prompt string. */
    4372           0 :         snprintf(buf, sizeof(buf), cmd_prompt(vty->node), cmd_hostname_get());
    4373             : #pragma GCC diagnostic pop
    4374           0 :         return buf;
    4375             : }
    4376             : 
    4377           0 : static void vtysh_ac_line(void *arg, const char *line)
    4378             : {
    4379           0 :         vector comps = arg;
    4380           0 :         size_t i;
    4381           0 :         for (i = 0; i < vector_active(comps); i++)
    4382           0 :                 if (!strcmp(line, (char *)vector_slot(comps, i)))
    4383             :                         return;
    4384           0 :         vector_set(comps, XSTRDUP(MTYPE_COMPLETION, line));
    4385             : }
    4386             : 
    4387           0 : static void vtysh_autocomplete(vector comps, struct cmd_token *token)
    4388             : {
    4389           0 :         char accmd[256];
    4390           0 :         size_t i;
    4391             : 
    4392           0 :         snprintf(accmd, sizeof(accmd), "autocomplete %d %s %s", token->type,
    4393           0 :                  token->text, token->varname ? token->varname : "-");
    4394             : 
    4395           0 :         vty->of_saved = vty->of;
    4396           0 :         vty->of = NULL;
    4397           0 :         for (i = 0; i < array_size(vtysh_client); i++)
    4398           0 :                 vtysh_client_run_all(&vtysh_client[i], accmd, 1, vtysh_ac_line,
    4399             :                                      comps);
    4400           0 :         vty->of = vty->of_saved;
    4401           0 : }
    4402             : 
    4403             : static const struct cmd_variable_handler vtysh_var_handler[] = {
    4404             :         {/* match all */
    4405             :          .tokenname = NULL,
    4406             :          .varname = NULL,
    4407             :          .completions = vtysh_autocomplete},
    4408             :         {.completions = NULL}};
    4409             : 
    4410           0 : void vtysh_uninit(void)
    4411             : {
    4412           0 :         if (vty->of != stdout)
    4413           0 :                 fclose(vty->of);
    4414           0 : }
    4415             : 
    4416           1 : void vtysh_init_vty(void)
    4417             : {
    4418           1 :         struct stat st_out, st_err;
    4419             : 
    4420           1 :         cmd_defer_tree(true);
    4421             : 
    4422          22 :         for (size_t i = 0; i < array_size(vtysh_client); i++) {
    4423          21 :                 vtysh_client[i].fd = -1;
    4424          21 :                 vtysh_client[i].log_fd = -1;
    4425             :         }
    4426             : 
    4427           1 :         stderr_tty = isatty(STDERR_FILENO);
    4428             : 
    4429           1 :         if (fstat(STDOUT_FILENO, &st_out) || fstat(STDERR_FILENO, &st_err) ||
    4430           1 :             (st_out.st_dev == st_err.st_dev && st_out.st_ino == st_err.st_ino))
    4431           0 :                 stderr_stdout_same = true;
    4432             : 
    4433             :         /* Make vty structure. */
    4434           1 :         vty = vty_new();
    4435           1 :         vty->type = VTY_SHELL;
    4436           1 :         vty->node = VIEW_NODE;
    4437             : 
    4438             :         /* set default output */
    4439           1 :         vty->of = stdout;
    4440           1 :         vtysh_pager_envdef(false);
    4441             : 
    4442             :         /* Initialize commands. */
    4443           1 :         cmd_init(0);
    4444           1 :         cmd_variable_handler_register(vtysh_var_handler);
    4445             : 
    4446             :         /* bgpd */
    4447             : #ifdef HAVE_BGPD
    4448           1 :         install_node(&bgp_node);
    4449           1 :         install_element(CONFIG_NODE, &router_bgp_cmd);
    4450           1 :         install_element(BGP_NODE, &vtysh_exit_bgpd_cmd);
    4451           1 :         install_element(BGP_NODE, &vtysh_quit_bgpd_cmd);
    4452           1 :         install_element(BGP_NODE, &vtysh_end_all_cmd);
    4453             : 
    4454           1 :         install_node(&bgp_vpnv4_node);
    4455           1 :         install_element(BGP_NODE, &address_family_ipv4_vpn_cmd);
    4456             : #ifdef KEEP_OLD_VPN_COMMANDS
    4457             :         install_element(BGP_NODE, &address_family_vpnv4_cmd);
    4458             : #endif /* KEEP_OLD_VPN_COMMANDS */
    4459           1 :         install_element(BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd);
    4460           1 :         install_element(BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd);
    4461           1 :         install_element(BGP_VPNV4_NODE, &vtysh_end_all_cmd);
    4462           1 :         install_element(BGP_VPNV4_NODE, &exit_address_family_cmd);
    4463             : 
    4464           1 :         install_node(&bgp_vpnv6_node);
    4465           1 :         install_element(BGP_NODE, &address_family_ipv6_vpn_cmd);
    4466             : #ifdef KEEP_OLD_VPN_COMMANDS
    4467             :         install_element(BGP_NODE, &address_family_vpnv6_cmd);
    4468             : #endif /* KEEP_OLD_VPN_COMMANDS */
    4469           1 :         install_element(BGP_VPNV6_NODE, &vtysh_exit_bgpd_cmd);
    4470           1 :         install_element(BGP_VPNV6_NODE, &vtysh_quit_bgpd_cmd);
    4471           1 :         install_element(BGP_VPNV6_NODE, &vtysh_end_all_cmd);
    4472           1 :         install_element(BGP_VPNV6_NODE, &exit_address_family_cmd);
    4473             : 
    4474           1 :         install_node(&bgp_flowspecv4_node);
    4475           1 :         install_element(BGP_NODE, &address_family_flowspecv4_cmd);
    4476           1 :         install_element(BGP_FLOWSPECV4_NODE, &vtysh_exit_bgpd_cmd);
    4477           1 :         install_element(BGP_FLOWSPECV4_NODE, &vtysh_quit_bgpd_cmd);
    4478           1 :         install_element(BGP_FLOWSPECV4_NODE, &vtysh_end_all_cmd);
    4479           1 :         install_element(BGP_FLOWSPECV4_NODE, &exit_address_family_cmd);
    4480             : 
    4481           1 :         install_node(&bgp_flowspecv6_node);
    4482           1 :         install_element(BGP_NODE, &address_family_flowspecv6_cmd);
    4483           1 :         install_element(BGP_FLOWSPECV6_NODE, &vtysh_exit_bgpd_cmd);
    4484           1 :         install_element(BGP_FLOWSPECV6_NODE, &vtysh_quit_bgpd_cmd);
    4485           1 :         install_element(BGP_FLOWSPECV6_NODE, &vtysh_end_all_cmd);
    4486           1 :         install_element(BGP_FLOWSPECV6_NODE, &exit_address_family_cmd);
    4487             : 
    4488           1 :         install_node(&bgp_ipv4_node);
    4489           1 :         install_element(BGP_NODE, &address_family_ipv4_cmd);
    4490           1 :         install_element(BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd);
    4491           1 :         install_element(BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd);
    4492           1 :         install_element(BGP_IPV4_NODE, &vtysh_end_all_cmd);
    4493           1 :         install_element(BGP_IPV4_NODE, &exit_address_family_cmd);
    4494             : 
    4495           1 :         install_node(&bgp_ipv4m_node);
    4496           1 :         install_element(BGP_NODE, &address_family_ipv4_multicast_cmd);
    4497           1 :         install_element(BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd);
    4498           1 :         install_element(BGP_IPV4M_NODE, &vtysh_quit_bgpd_cmd);
    4499           1 :         install_element(BGP_IPV4M_NODE, &vtysh_end_all_cmd);
    4500           1 :         install_element(BGP_IPV4M_NODE, &exit_address_family_cmd);
    4501             : 
    4502           1 :         install_node(&bgp_ipv4l_node);
    4503           1 :         install_element(BGP_NODE, &address_family_ipv4_labeled_unicast_cmd);
    4504           1 :         install_element(BGP_IPV4L_NODE, &vtysh_exit_bgpd_cmd);
    4505           1 :         install_element(BGP_IPV4L_NODE, &vtysh_quit_bgpd_cmd);
    4506           1 :         install_element(BGP_IPV4L_NODE, &vtysh_end_all_cmd);
    4507           1 :         install_element(BGP_IPV4L_NODE, &exit_address_family_cmd);
    4508             : 
    4509           1 :         install_node(&bgp_ipv6_node);
    4510           1 :         install_element(BGP_NODE, &address_family_ipv6_cmd);
    4511           1 :         install_element(BGP_IPV6_NODE, &vtysh_exit_bgpd_cmd);
    4512           1 :         install_element(BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd);
    4513           1 :         install_element(BGP_IPV6_NODE, &vtysh_end_all_cmd);
    4514           1 :         install_element(BGP_IPV6_NODE, &exit_address_family_cmd);
    4515             : 
    4516           1 :         install_node(&bgp_ipv6m_node);
    4517           1 :         install_element(BGP_NODE, &address_family_ipv6_multicast_cmd);
    4518           1 :         install_element(BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd);
    4519           1 :         install_element(BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd);
    4520           1 :         install_element(BGP_IPV6M_NODE, &vtysh_end_all_cmd);
    4521           1 :         install_element(BGP_IPV6M_NODE, &exit_address_family_cmd);
    4522             : 
    4523           1 :         install_node(&bgp_ipv6l_node);
    4524           1 :         install_element(BGP_NODE, &address_family_ipv6_labeled_unicast_cmd);
    4525           1 :         install_element(BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd);
    4526           1 :         install_element(BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd);
    4527           1 :         install_element(BGP_IPV6L_NODE, &vtysh_end_all_cmd);
    4528           1 :         install_element(BGP_IPV6L_NODE, &exit_address_family_cmd);
    4529             : 
    4530             : #if defined(ENABLE_BGP_VNC)
    4531           1 :         install_node(&bgp_vrf_policy_node);
    4532           1 :         install_element(BGP_NODE, &vnc_vrf_policy_cmd);
    4533           1 :         install_element(BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd);
    4534           1 :         install_element(BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd);
    4535           1 :         install_element(BGP_VRF_POLICY_NODE, &vtysh_end_all_cmd);
    4536           1 :         install_element(BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd);
    4537             : 
    4538           1 :         install_node(&bgp_vnc_defaults_node);
    4539           1 :         install_element(BGP_NODE, &vnc_defaults_cmd);
    4540           1 :         install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_exit_bgpd_cmd);
    4541           1 :         install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_quit_bgpd_cmd);
    4542           1 :         install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd);
    4543           1 :         install_element(BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd);
    4544             : 
    4545           1 :         install_node(&bgp_vnc_nve_group_node);
    4546           1 :         install_element(BGP_NODE, &vnc_nve_group_cmd);
    4547           1 :         install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_exit_bgpd_cmd);
    4548           1 :         install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_quit_bgpd_cmd);
    4549           1 :         install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd);
    4550           1 :         install_element(BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd);
    4551             : 
    4552           1 :         install_node(&bgp_vnc_l2_group_node);
    4553           1 :         install_element(BGP_NODE, &vnc_l2_group_cmd);
    4554           1 :         install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_exit_bgpd_cmd);
    4555           1 :         install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_quit_bgpd_cmd);
    4556           1 :         install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd);
    4557           1 :         install_element(BGP_VNC_L2_GROUP_NODE, &exit_vnc_config_cmd);
    4558             : #endif
    4559             : 
    4560           1 :         install_node(&bgp_evpn_node);
    4561           1 :         install_element(BGP_NODE, &address_family_evpn_cmd);
    4562           1 :         install_element(BGP_EVPN_NODE, &vtysh_quit_bgpd_cmd);
    4563           1 :         install_element(BGP_EVPN_NODE, &vtysh_exit_bgpd_cmd);
    4564           1 :         install_element(BGP_EVPN_NODE, &vtysh_end_all_cmd);
    4565           1 :         install_element(BGP_EVPN_NODE, &exit_address_family_cmd);
    4566             : 
    4567           1 :         install_node(&bgp_evpn_vni_node);
    4568           1 :         install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
    4569           1 :         install_element(BGP_EVPN_VNI_NODE, &vtysh_exit_bgpd_cmd);
    4570           1 :         install_element(BGP_EVPN_VNI_NODE, &vtysh_quit_bgpd_cmd);
    4571           1 :         install_element(BGP_EVPN_VNI_NODE, &vtysh_end_all_cmd);
    4572           1 :         install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
    4573             : 
    4574           1 :         install_node(&rpki_node);
    4575           1 :         install_element(CONFIG_NODE, &rpki_cmd);
    4576           1 :         install_element(RPKI_NODE, &rpki_exit_cmd);
    4577           1 :         install_element(RPKI_NODE, &rpki_quit_cmd);
    4578           1 :         install_element(RPKI_NODE, &vtysh_end_all_cmd);
    4579             : 
    4580           1 :         install_node(&bmp_node);
    4581           1 :         install_element(BGP_NODE, &bmp_targets_cmd);
    4582           1 :         install_element(BMP_NODE, &bmp_exit_cmd);
    4583           1 :         install_element(BMP_NODE, &bmp_quit_cmd);
    4584           1 :         install_element(BMP_NODE, &vtysh_end_all_cmd);
    4585             : 
    4586           1 :         install_node(&bgp_srv6_node);
    4587           1 :         install_element(BGP_NODE, &bgp_srv6_cmd);
    4588           1 :         install_element(BGP_SRV6_NODE, &exit_bgp_srv6_cmd);
    4589           1 :         install_element(BGP_SRV6_NODE, &quit_bgp_srv6_cmd);
    4590           1 :         install_element(BGP_SRV6_NODE, &vtysh_end_all_cmd);
    4591             : #endif /* HAVE_BGPD */
    4592             : 
    4593             :         /* ripd */
    4594           1 :         install_node(&rip_node);
    4595             : #ifdef HAVE_RIPD
    4596           1 :         install_element(CONFIG_NODE, &router_rip_cmd);
    4597           1 :         install_element(RIP_NODE, &vtysh_exit_ripd_cmd);
    4598           1 :         install_element(RIP_NODE, &vtysh_quit_ripd_cmd);
    4599           1 :         install_element(RIP_NODE, &vtysh_end_all_cmd);
    4600             : #endif /* HAVE_RIPD */
    4601             : 
    4602             :         /* ripngd */
    4603           1 :         install_node(&ripng_node);
    4604             : #ifdef HAVE_RIPNGD
    4605           1 :         install_element(CONFIG_NODE, &router_ripng_cmd);
    4606           1 :         install_element(RIPNG_NODE, &vtysh_exit_ripngd_cmd);
    4607           1 :         install_element(RIPNG_NODE, &vtysh_quit_ripngd_cmd);
    4608           1 :         install_element(RIPNG_NODE, &vtysh_end_all_cmd);
    4609             : #endif /* HAVE_RIPNGD */
    4610             : 
    4611             :         /* ospfd */
    4612             : #ifdef HAVE_OSPFD
    4613           1 :         install_node(&ospf_node);
    4614           1 :         install_element(CONFIG_NODE, &router_ospf_cmd);
    4615           1 :         install_element(OSPF_NODE, &vtysh_exit_ospfd_cmd);
    4616           1 :         install_element(OSPF_NODE, &vtysh_quit_ospfd_cmd);
    4617           1 :         install_element(OSPF_NODE, &vtysh_end_all_cmd);
    4618             : #endif /* HAVE_OSPFD */
    4619             : 
    4620             :         /* ospf6d */
    4621             : #ifdef HAVE_OSPF6D
    4622           1 :         install_node(&ospf6_node);
    4623           1 :         install_element(CONFIG_NODE, &router_ospf6_cmd);
    4624           1 :         install_element(OSPF6_NODE, &vtysh_exit_ospf6d_cmd);
    4625           1 :         install_element(OSPF6_NODE, &vtysh_quit_ospf6d_cmd);
    4626           1 :         install_element(OSPF6_NODE, &vtysh_end_all_cmd);
    4627             : #endif /* HAVE_OSPF6D */
    4628             : 
    4629             :         /* ldpd */
    4630             : #if defined(HAVE_LDPD)
    4631           1 :         install_node(&ldp_node);
    4632           1 :         install_element(CONFIG_NODE, &ldp_mpls_ldp_cmd);
    4633           1 :         install_element(LDP_NODE, &vtysh_exit_ldpd_cmd);
    4634           1 :         install_element(LDP_NODE, &vtysh_quit_ldpd_cmd);
    4635           1 :         install_element(LDP_NODE, &vtysh_end_all_cmd);
    4636             : 
    4637           1 :         install_node(&ldp_ipv4_node);
    4638           1 :         install_element(LDP_NODE, &ldp_address_family_ipv4_cmd);
    4639           1 :         install_element(LDP_IPV4_NODE, &vtysh_exit_ldpd_cmd);
    4640           1 :         install_element(LDP_IPV4_NODE, &vtysh_quit_ldpd_cmd);
    4641           1 :         install_element(LDP_IPV4_NODE, &ldp_exit_address_family_cmd);
    4642           1 :         install_element(LDP_IPV4_NODE, &vtysh_end_all_cmd);
    4643             : 
    4644           1 :         install_node(&ldp_ipv6_node);
    4645           1 :         install_element(LDP_NODE, &ldp_address_family_ipv6_cmd);
    4646           1 :         install_element(LDP_IPV6_NODE, &vtysh_exit_ldpd_cmd);
    4647           1 :         install_element(LDP_IPV6_NODE, &vtysh_quit_ldpd_cmd);
    4648           1 :         install_element(LDP_IPV6_NODE, &ldp_exit_address_family_cmd);
    4649           1 :         install_element(LDP_IPV6_NODE, &vtysh_end_all_cmd);
    4650             : 
    4651           1 :         install_node(&ldp_ipv4_iface_node);
    4652           1 :         install_element(LDP_IPV4_NODE, &ldp_interface_ifname_cmd);
    4653           1 :         install_element(LDP_IPV4_IFACE_NODE, &vtysh_exit_ldpd_cmd);
    4654           1 :         install_element(LDP_IPV4_IFACE_NODE, &vtysh_quit_ldpd_cmd);
    4655           1 :         install_element(LDP_IPV4_IFACE_NODE, &vtysh_end_all_cmd);
    4656             : 
    4657           1 :         install_node(&ldp_ipv6_iface_node);
    4658           1 :         install_element(LDP_IPV6_NODE, &ldp_interface_ifname_cmd);
    4659           1 :         install_element(LDP_IPV6_IFACE_NODE, &vtysh_exit_ldpd_cmd);
    4660           1 :         install_element(LDP_IPV6_IFACE_NODE, &vtysh_quit_ldpd_cmd);
    4661           1 :         install_element(LDP_IPV6_IFACE_NODE, &vtysh_end_all_cmd);
    4662             : 
    4663           1 :         install_node(&ldp_l2vpn_node);
    4664           1 :         install_element(CONFIG_NODE, &ldp_l2vpn_word_type_vpls_cmd);
    4665           1 :         install_element(LDP_L2VPN_NODE, &vtysh_exit_ldpd_cmd);
    4666           1 :         install_element(LDP_L2VPN_NODE, &vtysh_quit_ldpd_cmd);
    4667           1 :         install_element(LDP_L2VPN_NODE, &vtysh_end_all_cmd);
    4668             : 
    4669           1 :         install_node(&ldp_pseudowire_node);
    4670           1 :         install_element(LDP_L2VPN_NODE, &ldp_member_pseudowire_ifname_cmd);
    4671           1 :         install_element(LDP_PSEUDOWIRE_NODE, &vtysh_exit_ldpd_cmd);
    4672           1 :         install_element(LDP_PSEUDOWIRE_NODE, &vtysh_quit_ldpd_cmd);
    4673           1 :         install_element(LDP_PSEUDOWIRE_NODE, &vtysh_end_all_cmd);
    4674             : #endif
    4675             : 
    4676             :         /* eigrpd */
    4677             : #ifdef HAVE_EIGRPD
    4678           1 :         install_node(&eigrp_node);
    4679           1 :         install_element(CONFIG_NODE, &router_eigrp_cmd);
    4680           1 :         install_element(EIGRP_NODE, &vtysh_exit_eigrpd_cmd);
    4681           1 :         install_element(EIGRP_NODE, &vtysh_quit_eigrpd_cmd);
    4682           1 :         install_element(EIGRP_NODE, &vtysh_end_all_cmd);
    4683             : #endif /* HAVE_EIGRPD */
    4684             : 
    4685             :         /* babeld */
    4686             : #ifdef HAVE_BABELD
    4687           1 :         install_node(&babel_node);
    4688           1 :         install_element(CONFIG_NODE, &router_babel_cmd);
    4689           1 :         install_element(BABEL_NODE, &vtysh_exit_babeld_cmd);
    4690           1 :         install_element(BABEL_NODE, &vtysh_quit_babeld_cmd);
    4691           1 :         install_element(BABEL_NODE, &vtysh_end_all_cmd);
    4692             : #endif /* HAVE_BABELD */
    4693             : 
    4694             :         /* isisd */
    4695             : #ifdef HAVE_ISISD
    4696           1 :         install_node(&isis_node);
    4697           1 :         install_element(CONFIG_NODE, &router_isis_cmd);
    4698           1 :         install_element(ISIS_NODE, &vtysh_exit_isisd_cmd);
    4699           1 :         install_element(ISIS_NODE, &vtysh_quit_isisd_cmd);
    4700           1 :         install_element(ISIS_NODE, &vtysh_end_all_cmd);
    4701             : #endif /* HAVE_ISISD */
    4702             : 
    4703             :         /* fabricd */
    4704             : #ifdef HAVE_FABRICD
    4705           1 :         install_node(&openfabric_node);
    4706           1 :         install_element(CONFIG_NODE, &router_openfabric_cmd);
    4707           1 :         install_element(OPENFABRIC_NODE, &vtysh_exit_fabricd_cmd);
    4708           1 :         install_element(OPENFABRIC_NODE, &vtysh_quit_fabricd_cmd);
    4709           1 :         install_element(OPENFABRIC_NODE, &vtysh_end_all_cmd);
    4710             : #endif /* HAVE_FABRICD */
    4711             : 
    4712             :         /* pbrd */
    4713             : #ifdef HAVE_PBRD
    4714           1 :         install_node(&pbr_map_node);
    4715           1 :         install_element(CONFIG_NODE, &vtysh_pbr_map_cmd);
    4716           1 :         install_element(CONFIG_NODE, &vtysh_no_pbr_map_cmd);
    4717           1 :         install_element(PBRMAP_NODE, &vtysh_exit_pbr_map_cmd);
    4718           1 :         install_element(PBRMAP_NODE, &vtysh_quit_pbr_map_cmd);
    4719           1 :         install_element(PBRMAP_NODE, &vtysh_end_all_cmd);
    4720             : #endif /* HAVE_PBRD */
    4721             : 
    4722             :         /* bfdd */
    4723             : #if HAVE_BFDD > 0
    4724           1 :         install_node(&bfd_node);
    4725           1 :         install_element(CONFIG_NODE, &bfd_enter_cmd);
    4726           1 :         install_element(BFD_NODE, &vtysh_exit_bfdd_cmd);
    4727           1 :         install_element(BFD_NODE, &vtysh_quit_bfdd_cmd);
    4728           1 :         install_element(BFD_NODE, &vtysh_end_all_cmd);
    4729             : 
    4730           1 :         install_node(&bfd_peer_node);
    4731           1 :         install_element(BFD_NODE, &bfd_peer_enter_cmd);
    4732           1 :         install_element(BFD_PEER_NODE, &vtysh_exit_bfdd_cmd);
    4733           1 :         install_element(BFD_PEER_NODE, &vtysh_quit_bfdd_cmd);
    4734           1 :         install_element(BFD_PEER_NODE, &vtysh_end_all_cmd);
    4735             : 
    4736           1 :         install_node(&bfd_profile_node);
    4737           1 :         install_element(BFD_NODE, &bfd_profile_enter_cmd);
    4738           1 :         install_element(BFD_PROFILE_NODE, &vtysh_exit_bfdd_cmd);
    4739           1 :         install_element(BFD_PROFILE_NODE, &vtysh_quit_bfdd_cmd);
    4740           1 :         install_element(BFD_PROFILE_NODE, &vtysh_end_all_cmd);
    4741             : #endif /* HAVE_BFDD */
    4742             : 
    4743           1 :         install_node(&segment_routing_node);
    4744           1 :         install_element(CONFIG_NODE, &segment_routing_cmd);
    4745           1 :         install_element(SEGMENT_ROUTING_NODE, &vtysh_exit_sr_cmd);
    4746           1 :         install_element(SEGMENT_ROUTING_NODE, &vtysh_quit_sr_cmd);
    4747           1 :         install_element(SEGMENT_ROUTING_NODE, &vtysh_end_all_cmd);
    4748             : 
    4749             : #if defined(HAVE_PATHD)
    4750           1 :         install_node(&sr_traffic_eng_node);
    4751           1 :         install_node(&srte_segment_list_node);
    4752           1 :         install_node(&srte_policy_node);
    4753           1 :         install_node(&srte_candidate_dyn_node);
    4754             : 
    4755           1 :         install_element(SR_TRAFFIC_ENG_NODE, &vtysh_exit_pathd_cmd);
    4756           1 :         install_element(SR_TRAFFIC_ENG_NODE, &vtysh_quit_pathd_cmd);
    4757           1 :         install_element(SR_SEGMENT_LIST_NODE, &vtysh_exit_pathd_cmd);
    4758           1 :         install_element(SR_SEGMENT_LIST_NODE, &vtysh_quit_pathd_cmd);
    4759           1 :         install_element(SR_POLICY_NODE, &vtysh_exit_pathd_cmd);
    4760           1 :         install_element(SR_POLICY_NODE, &vtysh_quit_pathd_cmd);
    4761           1 :         install_element(SR_CANDIDATE_DYN_NODE, &vtysh_exit_pathd_cmd);
    4762           1 :         install_element(SR_CANDIDATE_DYN_NODE, &vtysh_quit_pathd_cmd);
    4763             : 
    4764             : 
    4765           1 :         install_element(SR_TRAFFIC_ENG_NODE, &vtysh_end_all_cmd);
    4766           1 :         install_element(SR_SEGMENT_LIST_NODE, &vtysh_end_all_cmd);
    4767           1 :         install_element(SR_POLICY_NODE, &vtysh_end_all_cmd);
    4768           1 :         install_element(SR_CANDIDATE_DYN_NODE, &vtysh_end_all_cmd);
    4769             : 
    4770           1 :         install_element(SEGMENT_ROUTING_NODE, &sr_traffic_eng_cmd);
    4771           1 :         install_element(SR_TRAFFIC_ENG_NODE, &srte_segment_list_cmd);
    4772           1 :         install_element(SR_TRAFFIC_ENG_NODE, &srte_policy_cmd);
    4773           1 :         install_element(SR_POLICY_NODE, &srte_policy_candidate_dyn_path_cmd);
    4774             : 
    4775           1 :         install_node(&pcep_node);
    4776           1 :         install_node(&pcep_pcc_node);
    4777           1 :         install_node(&pcep_pce_node);
    4778           1 :         install_node(&pcep_pce_config_node);
    4779             : 
    4780           1 :         install_element(PCEP_NODE, &vtysh_exit_pathd_cmd);
    4781           1 :         install_element(PCEP_NODE, &vtysh_quit_pathd_cmd);
    4782           1 :         install_element(PCEP_PCC_NODE, &vtysh_exit_pathd_cmd);
    4783           1 :         install_element(PCEP_PCC_NODE, &vtysh_quit_pathd_cmd);
    4784           1 :         install_element(PCEP_PCE_NODE, &vtysh_exit_pathd_cmd);
    4785           1 :         install_element(PCEP_PCE_NODE, &vtysh_quit_pathd_cmd);
    4786           1 :         install_element(PCEP_PCE_CONFIG_NODE, &vtysh_exit_pathd_cmd);
    4787           1 :         install_element(PCEP_PCE_CONFIG_NODE, &vtysh_quit_pathd_cmd);
    4788             : 
    4789           1 :         install_element(PCEP_NODE, &vtysh_end_all_cmd);
    4790           1 :         install_element(PCEP_PCC_NODE, &vtysh_end_all_cmd);
    4791           1 :         install_element(PCEP_PCE_NODE, &vtysh_end_all_cmd);
    4792           1 :         install_element(PCEP_PCE_CONFIG_NODE, &vtysh_end_all_cmd);
    4793             : 
    4794           1 :         install_element(SR_TRAFFIC_ENG_NODE, &pcep_cmd);
    4795           1 :         install_element(PCEP_NODE, &pcep_cli_pcc_cmd);
    4796           1 :         install_element(PCEP_NODE, &pcep_cli_pcep_pce_config_cmd);
    4797           1 :         install_element(PCEP_NODE, &pcep_cli_pce_cmd);
    4798             : 
    4799             : #endif /* HAVE_PATHD */
    4800             : 
    4801             :         /* keychain */
    4802           1 :         install_node(&keychain_node);
    4803           1 :         install_element(CONFIG_NODE, &key_chain_cmd);
    4804           1 :         install_element(KEYCHAIN_NODE, &key_chain_cmd);
    4805           1 :         install_element(KEYCHAIN_NODE, &vtysh_exit_keys_cmd);
    4806           1 :         install_element(KEYCHAIN_NODE, &vtysh_quit_keys_cmd);
    4807           1 :         install_element(KEYCHAIN_NODE, &vtysh_end_all_cmd);
    4808             : 
    4809           1 :         install_node(&keychain_key_node);
    4810           1 :         install_element(KEYCHAIN_NODE, &key_cmd);
    4811           1 :         install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd);
    4812           1 :         install_element(KEYCHAIN_KEY_NODE, &vtysh_exit_keys_cmd);
    4813           1 :         install_element(KEYCHAIN_KEY_NODE, &vtysh_quit_keys_cmd);
    4814           1 :         install_element(KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
    4815             : 
    4816             :         /* nexthop-group */
    4817           1 :         install_node(&nh_group_node);
    4818           1 :         install_element(CONFIG_NODE, &vtysh_nexthop_group_cmd);
    4819           1 :         install_element(CONFIG_NODE, &vtysh_no_nexthop_group_cmd);
    4820           1 :         install_element(NH_GROUP_NODE, &vtysh_end_all_cmd);
    4821           1 :         install_element(NH_GROUP_NODE, &vtysh_exit_nexthop_group_cmd);
    4822           1 :         install_element(NH_GROUP_NODE, &vtysh_quit_nexthop_group_cmd);
    4823             : 
    4824             :         /* zebra and all */
    4825           1 :         install_node(&zebra_node);
    4826             : 
    4827           1 :         install_node(&interface_node);
    4828           1 :         install_element(CONFIG_NODE, &vtysh_interface_cmd);
    4829           1 :         install_element(INTERFACE_NODE, &vtysh_end_all_cmd);
    4830           1 :         install_element(INTERFACE_NODE, &vtysh_exit_interface_cmd);
    4831           1 :         install_element(INTERFACE_NODE, &vtysh_quit_interface_cmd);
    4832             : 
    4833           1 :         install_node(&link_params_node);
    4834           1 :         install_element(INTERFACE_NODE, &vtysh_link_params_cmd);
    4835           1 :         install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
    4836           1 :         install_element(LINK_PARAMS_NODE, &vtysh_end_all_cmd);
    4837           1 :         install_element(LINK_PARAMS_NODE, &vtysh_exit_link_params_cmd);
    4838           1 :         install_element(LINK_PARAMS_NODE, &vtysh_quit_link_params_cmd);
    4839             : 
    4840           1 :         install_node(&pw_node);
    4841           1 :         install_element(CONFIG_NODE, &vtysh_pseudowire_cmd);
    4842           1 :         install_element(PW_NODE, &vtysh_end_all_cmd);
    4843           1 :         install_element(PW_NODE, &vtysh_exit_pseudowire_cmd);
    4844           1 :         install_element(PW_NODE, &vtysh_quit_pseudowire_cmd);
    4845             : 
    4846           1 :         install_node(&vrf_node);
    4847           1 :         install_element(CONFIG_NODE, &vtysh_vrf_cmd);
    4848           1 :         install_element(VRF_NODE, &exit_vrf_config_cmd);
    4849           1 :         install_element(VRF_NODE, &vtysh_end_all_cmd);
    4850           1 :         install_element(VRF_NODE, &vtysh_exit_vrf_cmd);
    4851           1 :         install_element(VRF_NODE, &vtysh_quit_vrf_cmd);
    4852             : 
    4853           1 :         install_node(&rmap_node);
    4854           1 :         install_element(CONFIG_NODE, &vtysh_route_map_cmd);
    4855           1 :         install_element(RMAP_NODE, &vtysh_exit_rmap_cmd);
    4856           1 :         install_element(RMAP_NODE, &vtysh_quit_rmap_cmd);
    4857           1 :         install_element(RMAP_NODE, &vtysh_end_all_cmd);
    4858             : 
    4859           1 :         install_node(&vty_node);
    4860           1 :         install_element(CONFIG_NODE, &vtysh_line_vty_cmd);
    4861           1 :         install_element(VTY_NODE, &vtysh_exit_line_vty_cmd);
    4862           1 :         install_element(VTY_NODE, &vtysh_quit_line_vty_cmd);
    4863           1 :         install_element(VTY_NODE, &vtysh_end_all_cmd);
    4864             : 
    4865             : 
    4866           1 :         struct cmd_node *node;
    4867          93 :         for (unsigned int i = 0; i < vector_active(cmdvec); i++) {
    4868          92 :                 node = vector_slot(cmdvec, i);
    4869          92 :                 if (!node || node->node == VIEW_NODE)
    4870          30 :                         continue;
    4871          62 :                 vtysh_install_default(node->node);
    4872             :         }
    4873             : 
    4874             :         /* vtysh */
    4875             : 
    4876           1 :         if (!user_mode)
    4877           1 :                 install_element(VIEW_NODE, &vtysh_enable_cmd);
    4878           1 :         install_element(ENABLE_NODE, &vtysh_config_terminal_cmd);
    4879           1 :         install_element(ENABLE_NODE, &vtysh_disable_cmd);
    4880             : 
    4881             :         /* "exit" command. */
    4882           1 :         install_element(VIEW_NODE, &vtysh_exit_all_cmd);
    4883           1 :         install_element(CONFIG_NODE, &vtysh_exit_all_cmd);
    4884           1 :         install_element(VIEW_NODE, &vtysh_quit_all_cmd);
    4885           1 :         install_element(CONFIG_NODE, &vtysh_quit_all_cmd);
    4886             : 
    4887             :         /* "end" command. */
    4888           1 :         install_element(CONFIG_NODE, &vtysh_end_all_cmd);
    4889           1 :         install_element(ENABLE_NODE, &vtysh_end_all_cmd);
    4890             : 
    4891             :         /* SRv6 Data-plane */
    4892           1 :         install_node(&srv6_node);
    4893           1 :         install_element(SEGMENT_ROUTING_NODE, &srv6_cmd);
    4894           1 :         install_element(SRV6_NODE, &srv6_locators_cmd);
    4895           1 :         install_element(SRV6_NODE, &exit_srv6_config_cmd);
    4896           1 :         install_element(SRV6_NODE, &vtysh_end_all_cmd);
    4897             : 
    4898           1 :         install_node(&srv6_locs_node);
    4899           1 :         install_element(SRV6_LOCS_NODE, &srv6_locator_cmd);
    4900           1 :         install_element(SRV6_LOCS_NODE, &exit_srv6_locs_config_cmd);
    4901           1 :         install_element(SRV6_LOCS_NODE, &vtysh_end_all_cmd);
    4902             : 
    4903           1 :         install_node(&srv6_loc_node);
    4904           1 :         install_element(SRV6_LOC_NODE, &exit_srv6_loc_config_cmd);
    4905           1 :         install_element(SRV6_LOC_NODE, &vtysh_end_all_cmd);
    4906             : 
    4907           1 :         install_element(ENABLE_NODE, &vtysh_show_running_config_cmd);
    4908           1 :         install_element(ENABLE_NODE, &vtysh_copy_running_config_cmd);
    4909           1 :         install_element(ENABLE_NODE, &vtysh_copy_to_running_cmd);
    4910             : 
    4911             :         /* "write terminal" command. */
    4912           1 :         install_element(ENABLE_NODE, &vtysh_write_terminal_cmd);
    4913             : 
    4914           1 :         install_element(CONFIG_NODE, &vtysh_integrated_config_cmd);
    4915           1 :         install_element(CONFIG_NODE, &no_vtysh_integrated_config_cmd);
    4916             : 
    4917             :         /* "write memory" command. */
    4918           1 :         install_element(ENABLE_NODE, &vtysh_write_memory_cmd);
    4919             : 
    4920           1 :         install_element(CONFIG_NODE, &start_config_cmd);
    4921           1 :         install_element(CONFIG_NODE, &end_config_cmd);
    4922             : 
    4923           1 :         install_element(CONFIG_NODE, &vtysh_terminal_paginate_cmd);
    4924           1 :         install_element(VIEW_NODE, &vtysh_terminal_paginate_cmd);
    4925           1 :         install_element(VIEW_NODE, &vtysh_terminal_length_cmd);
    4926           1 :         install_element(VIEW_NODE, &vtysh_terminal_no_length_cmd);
    4927           1 :         install_element(VIEW_NODE, &vtysh_show_daemons_cmd);
    4928             : 
    4929           1 :         install_element(VIEW_NODE, &vtysh_terminal_monitor_cmd);
    4930           1 :         install_element(VIEW_NODE, &no_vtysh_terminal_monitor_cmd);
    4931             : 
    4932           1 :         install_element(VIEW_NODE, &vtysh_ping_cmd);
    4933           1 :         install_element(VIEW_NODE, &vtysh_motd_cmd);
    4934           1 :         install_element(VIEW_NODE, &vtysh_ping_ip_cmd);
    4935           1 :         install_element(VIEW_NODE, &vtysh_traceroute_cmd);
    4936           1 :         install_element(VIEW_NODE, &vtysh_traceroute_ip_cmd);
    4937           1 :         install_element(VIEW_NODE, &vtysh_mtrace_cmd);
    4938           1 :         install_element(VIEW_NODE, &vtysh_ping6_cmd);
    4939           1 :         install_element(VIEW_NODE, &vtysh_traceroute6_cmd);
    4940             : #if defined(HAVE_SHELL_ACCESS)
    4941             :         install_element(VIEW_NODE, &vtysh_telnet_cmd);
    4942             :         install_element(VIEW_NODE, &vtysh_telnet_port_cmd);
    4943             :         install_element(VIEW_NODE, &vtysh_ssh_cmd);
    4944             : #endif
    4945             : #if defined(HAVE_SHELL_ACCESS)
    4946             :         install_element(ENABLE_NODE, &vtysh_start_shell_cmd);
    4947             :         install_element(ENABLE_NODE, &vtysh_start_bash_cmd);
    4948             :         install_element(ENABLE_NODE, &vtysh_start_zsh_cmd);
    4949             : #endif
    4950             : 
    4951             :         /* debugging */
    4952           1 :         install_element(VIEW_NODE, &vtysh_show_error_code_cmd);
    4953           1 :         install_element(ENABLE_NODE, &vtysh_show_debugging_cmd);
    4954           1 :         install_element(ENABLE_NODE, &vtysh_show_debugging_hashtable_cmd);
    4955           1 :         install_element(ENABLE_NODE, &vtysh_debug_all_cmd);
    4956           1 :         install_element(CONFIG_NODE, &vtysh_debug_all_cmd);
    4957           1 :         install_element(ENABLE_NODE, &vtysh_debug_memstats_cmd);
    4958           1 :         install_element(CONFIG_NODE, &vtysh_debug_memstats_cmd);
    4959           1 :         install_element(ENABLE_NODE, &vtysh_debug_uid_backtrace_cmd);
    4960           1 :         install_element(CONFIG_NODE, &vtysh_debug_uid_backtrace_cmd);
    4961             : 
    4962             :         /* northbound */
    4963           1 :         install_element(ENABLE_NODE, &show_config_running_cmd);
    4964           1 :         install_element(ENABLE_NODE, &show_yang_operational_data_cmd);
    4965           1 :         install_element(ENABLE_NODE, &show_yang_module_cmd);
    4966           1 :         install_element(ENABLE_NODE, &show_yang_module_detail_cmd);
    4967           1 :         install_element(ENABLE_NODE, &debug_nb_cmd);
    4968           1 :         install_element(CONFIG_NODE, &debug_nb_cmd);
    4969             : 
    4970             :         /* misc lib show commands */
    4971           1 :         install_element(VIEW_NODE, &vtysh_show_history_cmd);
    4972           1 :         install_element(VIEW_NODE, &vtysh_show_memory_cmd);
    4973           1 :         install_element(VIEW_NODE, &vtysh_show_modules_cmd);
    4974           1 :         install_element(VIEW_NODE, &vtysh_show_work_queues_cmd);
    4975           1 :         install_element(VIEW_NODE, &vtysh_show_work_queues_daemon_cmd);
    4976           1 :         install_element(VIEW_NODE, &vtysh_show_thread_cmd);
    4977           1 :         install_element(VIEW_NODE, &vtysh_show_poll_cmd);
    4978           1 :         install_element(VIEW_NODE, &vtysh_show_thread_timer_cmd);
    4979             : 
    4980             :         /* Logging */
    4981           1 :         install_element(VIEW_NODE, &vtysh_show_logging_cmd);
    4982             : 
    4983           1 :         install_element(CONFIG_NODE, &vtysh_service_password_encrypt_cmd);
    4984           1 :         install_element(CONFIG_NODE, &no_vtysh_service_password_encrypt_cmd);
    4985             : 
    4986           1 :         install_element(CONFIG_NODE, &vtysh_allow_reserved_ranges_cmd);
    4987           1 :         install_element(CONFIG_NODE, &no_vtysh_allow_reserved_ranges_cmd);
    4988             : 
    4989           1 :         install_element(CONFIG_NODE, &vtysh_password_cmd);
    4990           1 :         install_element(CONFIG_NODE, &no_vtysh_password_cmd);
    4991           1 :         install_element(CONFIG_NODE, &vtysh_enable_password_cmd);
    4992           1 :         install_element(CONFIG_NODE, &no_vtysh_enable_password_cmd);
    4993           1 : }

Generated by: LCOV version v1.16-topotato