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