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