1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Virtual terminal interface shell.
3 * Copyright (C) 2000 Kunihiro Ishiguro
11 #include <sys/resource.h>
14 /* readline carries some ancient definitions around */
15 #pragma GCC diagnostic push
16 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
17 #include <readline/readline.h>
18 #include <readline/history.h>
19 #pragma GCC diagnostic pop
30 #include "vtysh/vtysh.h"
31 #include "vtysh/vtysh_daemons.h"
35 #include "command_graph.h"
39 #include "bgpd/bgp_vty.h"
41 DEFINE_MTYPE_STATIC(MVTYSH
, VTYSH_CMD
, "Vtysh cmd copy");
46 /* VTY shell pager name. */
47 char *vtysh_pager_name
= NULL
;
49 /* VTY should add timestamp */
50 bool vtysh_add_timestamp
;
52 static bool stderr_tty
;
53 static bool stderr_stdout_same
;
55 /* Some utility functions for working on vtysh-specific vty tasks */
57 static FILE *vty_open_pager(struct vty
*vty
)
62 if (!vtysh_pager_name
)
65 vty
->of_saved
= vty
->of
;
66 vty
->of
= popen(vtysh_pager_name
, "w");
67 if (vty
->of
== NULL
) {
68 vty
->of
= vty
->of_saved
;
78 static int vty_close_pager(struct vty
*vty
)
84 if (pclose(vty
->of
) == -1) {
89 vty
->of
= vty
->of_saved
;
90 vty
->is_paged
= false;
95 static void vtysh_pager_envdef(bool fallback
)
99 pager_defined
= getenv("VTYSH_PAGER");
102 vtysh_pager_name
= strdup(pager_defined
);
104 vtysh_pager_name
= strdup(VTYSH_PAGER
);
110 * When updating this array, remember to change the array size here and in
113 struct vtysh_client vtysh_client
[] = {
114 {.name
= "mgmtd", .flag
= VTYSH_MGMTD
},
115 {.name
= "zebra", .flag
= VTYSH_ZEBRA
},
116 {.name
= "ripd", .flag
= VTYSH_RIPD
},
117 {.name
= "ripngd", .flag
= VTYSH_RIPNGD
},
118 {.name
= "ospfd", .flag
= VTYSH_OSPFD
},
119 {.name
= "ospf6d", .flag
= VTYSH_OSPF6D
},
120 {.name
= "ldpd", .flag
= VTYSH_LDPD
},
121 {.name
= "bgpd", .flag
= VTYSH_BGPD
},
122 {.name
= "isisd", .flag
= VTYSH_ISISD
},
123 {.name
= "pimd", .flag
= VTYSH_PIMD
},
124 {.name
= "nhrpd", .flag
= VTYSH_NHRPD
},
125 {.name
= "eigrpd", .flag
= VTYSH_EIGRPD
},
126 {.name
= "babeld", .flag
= VTYSH_BABELD
},
127 {.name
= "sharpd", .flag
= VTYSH_SHARPD
},
128 {.name
= "fabricd", .flag
= VTYSH_FABRICD
},
129 {.name
= "watchfrr", .flag
= VTYSH_WATCHFRR
},
130 {.name
= "pbrd", .flag
= VTYSH_PBRD
},
131 {.name
= "staticd", .flag
= VTYSH_STATICD
},
132 {.name
= "bfdd", .flag
= VTYSH_BFDD
},
133 {.name
= "vrrpd", .flag
= VTYSH_VRRPD
},
134 {.name
= "pathd", .flag
= VTYSH_PATHD
},
135 {.name
= "pim6d", .flag
= VTYSH_PIM6D
},
138 /* Searches for client by name, returns index */
139 static int vtysh_client_lookup(const char *name
)
143 for (unsigned int i
= 0; i
< array_size(vtysh_client
); i
++) {
144 if (strmatch(vtysh_client
[i
].name
, name
)) {
153 enum vtysh_write_integrated vtysh_write_integrated
=
154 WRITE_INTEGRATED_UNSPECIFIED
;
156 static int vtysh_reconnect(struct vtysh_client
*vclient
);
158 static void vclient_close(struct vtysh_client
*vclient
)
160 if (vclient
->fd
>= 0) {
163 "Warning: closing connection to %s because of an I/O error!\n",
166 /* indicate as candidate for reconnect */
167 vclient
->fd
= VTYSH_WAS_ACTIVE
;
171 static ssize_t
vtysh_client_receive(struct vtysh_client
*vclient
, char *buf
,
172 size_t bufsz
, int *pass_fd
)
174 struct iovec iov
[1] = {
181 uint8_t buf
[CMSG_SPACE(sizeof(int))];
182 struct cmsghdr align
;
186 .msg_iovlen
= array_size(iov
),
187 .msg_control
= u
.buf
,
188 .msg_controllen
= sizeof(u
.buf
),
190 struct cmsghdr
*cmh
= CMSG_FIRSTHDR(&mh
);
193 cmh
->cmsg_level
= SOL_SOCKET
;
194 cmh
->cmsg_type
= SCM_RIGHTS
;
195 cmh
->cmsg_len
= CMSG_LEN(sizeof(int));
196 memset(CMSG_DATA(cmh
), -1, sizeof(int));
199 ret
= recvmsg(vclient
->fd
, &mh
, 0);
200 if (ret
>= 0 || (errno
!= EINTR
&& errno
!= EAGAIN
))
204 if (cmh
->cmsg_len
== CMSG_LEN(sizeof(int))) {
207 memcpy(&fd
, CMSG_DATA(cmh
), sizeof(int));
219 * Send a CLI command to a client and read the response.
221 * Output will be printed to vty->of. If you want to suppress output, set that
225 * the client to send the command to
228 * the command to send
231 * if non-null, this will be called with each line of output received from
232 * the client passed in the second parameter
235 * optional first argument to pass to callback
240 static int vtysh_client_run(struct vtysh_client
*vclient
, const char *line
,
241 void (*callback
)(void *, const char *), void *cbarg
,
246 char *buf
= stackbuf
;
247 size_t bufsz
= sizeof(stackbuf
);
248 char *bufvalid
, *end
= NULL
;
249 char terminator
[3] = {0, 0, 0};
251 /* vclinet was previously active, try to reconnect */
252 if (vclient
->fd
== VTYSH_WAS_ACTIVE
) {
253 ret
= vtysh_reconnect(vclient
);
261 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
263 /* close connection and try to reconnect */
264 vclient_close(vclient
);
265 ret
= vtysh_reconnect(vclient
);
269 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
278 nread
= vtysh_client_receive(
279 vclient
, bufvalid
, buf
+ bufsz
- bufvalid
- 1, pass_fd
);
281 if (nread
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
287 "vtysh: error reading from %s: %s (%d)",
288 vclient
->name
, safe_strerror(errno
),
295 /* Null terminate so we may pass this to *printf later. */
299 * We expect string output from daemons, so instead of looking
300 * for the full 3 null bytes of the terminator, we check for
301 * just one instead and assume it is the first byte of the
302 * terminator. The presence of the full terminator is checked
305 if (bufvalid
- buf
>= 4)
306 end
= memmem(bufvalid
- 4, 4, "\0", 1);
309 * calculate # bytes we have, up to & not including the
310 * terminator if present
312 size_t textlen
= (end
? end
: bufvalid
) - buf
;
315 /* feed line processing callback if present */
316 while (callback
&& bufvalid
> buf
&& (end
> buf
|| !end
)) {
317 textlen
= (end
? end
: bufvalid
) - buf
;
318 char *eol
= memchr(buf
, '\n', textlen
);
324 * no line break, end of input, no text left
325 * before end; nothing to write
329 /* no nl, end of input, but some text left */
331 else if (bufvalid
== buf
+ bufsz
- 1) {
333 * no nl, no end of input, no buffer space;
339 if (buf
== stackbuf
) {
340 new = XMALLOC(MTYPE_TMP
, bufsz
);
341 memcpy(new, stackbuf
, sizeof(stackbuf
));
343 new = XREALLOC(MTYPE_TMP
, buf
, bufsz
);
345 bufvalid
= bufvalid
- buf
+ new;
347 /* if end != NULL, we won't be reading more
357 /* eol is at line end now, either \n => \0 or \0\0\0 */
358 assert(eol
&& eol
<= bufvalid
);
361 vty_out(vty
, "%s\n", buf
);
363 callback(cbarg
, buf
);
365 /* shift back data and adjust bufvalid */
366 memmove(buf
, eol
, bufvalid
- eol
);
367 bufvalid
-= eol
- buf
;
372 /* else if no callback, dump raw */
375 vty_out(vty
, "%s", buf
);
376 memmove(buf
, buf
+ textlen
, bufvalid
- buf
- textlen
);
382 * ----------------------------------------------------
383 * At this point `buf` should be in one of two states:
384 * - Empty (i.e. buf == bufvalid)
385 * - Contains up to 4 bytes of the terminator
386 * ----------------------------------------------------
388 assert(((buf
== bufvalid
)
389 || (bufvalid
- buf
<= 4 && buf
[0] == 0x00)));
392 /* if we have the terminator, break */
393 if (end
&& bufvalid
- buf
== 4) {
394 assert(!memcmp(buf
, terminator
, 3));
403 vclient_close(vclient
);
407 XFREE(MTYPE_TMP
, buf
);
411 static int vtysh_client_run_all(struct vtysh_client
*head_client
,
412 const char *line
, int continue_on_err
,
413 void (*callback
)(void *, const char *),
416 struct vtysh_client
*client
;
417 int rc
, rc_all
= CMD_SUCCESS
;
418 int correct_instance
= 0, wrong_instance
= 0;
420 for (client
= head_client
; client
; client
= client
->next
) {
421 rc
= vtysh_client_run(client
, line
, callback
, cbarg
, NULL
);
422 if (rc
== CMD_NOT_MY_INSTANCE
) {
428 if (rc
!= CMD_SUCCESS
) {
429 if (!continue_on_err
)
434 if (wrong_instance
&& !correct_instance
&& vty
->of
) {
436 "%% [%s]: command ignored as it targets an instance that is not running\n",
438 rc_all
= CMD_WARNING_CONFIG_FAILED
;
444 * Execute command against all daemons.
447 * where to start walking in the daemon list
450 * the specific command to execute
455 static int vtysh_client_execute(struct vtysh_client
*head_client
,
458 return vtysh_client_run_all(head_client
, line
, 0, NULL
, NULL
);
461 /* Execute by name */
462 static int vtysh_client_execute_name(const char *name
, const char *line
)
464 int ret
= CMD_SUCCESS
;
467 idx_client
= vtysh_client_lookup(name
);
468 if (idx_client
!= -1)
469 ret
= vtysh_client_execute(&vtysh_client
[idx_client
], line
);
471 vty_out(vty
, "Client not found\n");
479 * Retrieve all running config from daemons and parse it with the vtysh config
480 * parser. Returned output is not displayed to the user.
483 * where to start walking in the daemon list
486 * the specific command to execute
488 static void vtysh_client_config(struct vtysh_client
*head_client
, char *line
)
490 /* watchfrr currently doesn't load any config, and has some hardcoded
491 * settings that show up in "show run". skip it here (for now at
492 * least) so we don't get that mangled up in config-write.
494 if (head_client
->flag
== VTYSH_WATCHFRR
)
497 /* suppress output to user */
498 vty
->of_saved
= vty
->of
;
500 vtysh_client_run_all(head_client
, line
, 1, vtysh_config_parse_line
,
502 vty
->of
= vty
->of_saved
;
505 /* Command execution over the vty interface. */
506 static int vtysh_execute_func(const char *line
, int pager
)
511 const struct cmd_element
*cmd
;
513 int saved_ret
, saved_node
;
515 /* Split readline string up into the vector. */
516 vline
= cmd_make_strvec(line
);
521 if (vtysh_add_timestamp
&& strncmp(line
, "exit", 4)) {
524 (void)frr_timestamp(3, ts
, sizeof(ts
));
525 vty_out(vty
, "%% %s\n\n", ts
);
528 saved_ret
= ret
= cmd_execute(vty
, line
, &cmd
, 1);
529 saved_node
= vty
->node
;
532 * If command doesn't succeeded in current node, try to walk up in node
533 * tree. Changing vty->node is enough to try it just out without actual
534 * walkup in the vtysh.
536 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
537 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
538 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
539 && vty
->node
> CONFIG_NODE
) {
540 vty
->node
= node_parent(vty
->node
);
541 ret
= cmd_execute(vty
, line
, &cmd
, 1);
545 vty
->node
= saved_node
;
548 * If command succeeded in any other node than current (tried > 0) we
549 * have to move into node in the vtysh where it succeeded.
551 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
552 || ret
== CMD_WARNING
) {
554 vtysh_execute("exit");
557 * If command didn't succeed in any node, continue with return value
564 cmd_free_strvec(vline
);
569 case CMD_WARNING_CONFIG_FAILED
:
570 if (vty
->type
== VTY_FILE
)
571 vty_out(vty
, "Warning...\n");
573 case CMD_ERR_AMBIGUOUS
:
574 vty_out(vty
, "%% Ambiguous command: %s\n", line
);
576 case CMD_ERR_NO_MATCH
:
577 vty_out(vty
, "%% Unknown command: %s\n", line
);
579 case CMD_ERR_INCOMPLETE
:
580 vty_out(vty
, "%% Command incomplete: %s\n", line
);
582 case CMD_SUCCESS_DAEMON
: {
584 * FIXME: Don't open pager for exit commands. popen() causes
585 * problems if exited from vtysh at all. This hack shouldn't
586 * cause any problem but is really ugly.
588 if (pager
&& strncmp(line
, "exit", 4))
591 if (!strcmp(cmd
->string
, "configure")) {
592 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
593 cmd_stat
= vtysh_client_execute(
594 &vtysh_client
[i
], line
);
595 if (cmd_stat
== CMD_WARNING
)
601 vline
= cmd_make_strvec(line
);
606 vty_close_pager(vty
);
610 ret
= cmd_execute_command(vline
, vty
, &cmd
, 1);
611 cmd_free_strvec(vline
);
612 if (ret
!= CMD_SUCCESS_DAEMON
)
614 } else if (cmd
->func
) {
615 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
620 cmd_stat
= CMD_SUCCESS
;
621 struct vtysh_client
*vc
;
622 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
623 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
624 if (vtysh_client
[i
].fd
< 0
625 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
626 for (vc
= &vtysh_client
[i
]; vc
;
628 if (vc
->fd
== VTYSH_WAS_ACTIVE
)
631 if (vtysh_client
[i
].fd
< 0
632 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
633 bool any_inst
= false;
634 for (vc
= &vtysh_client
[i
]; vc
;
640 "%s is not running\n",
641 vtysh_client
[i
].name
);
642 cmd_stat
= CMD_ERR_NO_DAEMON
;
646 cmd_stat
= vtysh_client_execute(
647 &vtysh_client
[i
], line
);
648 if (cmd_stat
!= CMD_SUCCESS
)
652 if (cmd_stat
!= CMD_SUCCESS
&& cmd_stat
!= CMD_ERR_NO_DAEMON
)
656 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
660 vty_close_pager(vty
);
665 int vtysh_execute_no_pager(const char *line
)
667 return vtysh_execute_func(line
, 0);
670 int vtysh_execute(const char *line
)
672 return vtysh_execute_func(line
, 1);
675 static char *trim(char *s
)
686 while (end
>= s
&& isspace((unsigned char)*end
))
690 while (*s
&& isspace((unsigned char)*s
))
696 int vtysh_mark_file(const char *filename
)
703 const struct cmd_element
*cmd
;
704 int saved_ret
, prev_node
;
706 char *vty_buf_copy
= NULL
;
707 char *vty_buf_trimmed
= NULL
;
709 if (strncmp("-", filename
, 1) == 0)
712 confp
= fopen(filename
, "r");
715 fprintf(stderr
, "%% Can't open config file %s due to '%s'.\n",
716 filename
, safe_strerror(errno
));
717 return CMD_ERR_NO_FILE
;
721 vty
->wfd
= STDOUT_FILENO
;
722 vty
->type
= VTY_TERM
;
723 vty
->node
= CONFIG_NODE
;
725 vtysh_execute_no_pager("enable");
726 vtysh_execute_no_pager("configure");
727 vty_buf_copy
= XCALLOC(MTYPE_VTYSH_CMD
, VTY_BUFSIZ
);
729 while (fgets(vty
->buf
, VTY_BUFSIZ
, confp
)) {
732 strlcpy(vty_buf_copy
, vty
->buf
, VTY_BUFSIZ
);
733 vty_buf_trimmed
= trim(vty_buf_copy
);
735 if (vty_buf_trimmed
[0] == '!' || vty_buf_trimmed
[0] == '#') {
736 vty_out(vty
, "%s", vty
->buf
);
740 /* Split readline string up into the vector. */
741 vline
= cmd_make_strvec(vty
->buf
);
744 vty_out(vty
, "%s", vty
->buf
);
749 * Ignore the "end" lines, we will generate these where
752 if (strlen(vty_buf_trimmed
) == 3
753 && strncmp("end", vty_buf_trimmed
, 3) == 0) {
754 cmd_free_strvec(vline
);
758 prev_node
= vty
->node
;
759 saved_ret
= ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
762 * If command doesn't succeeded in current node, try to walk up
763 * in node tree. Changing vty->node is enough to try it just
764 * out without actual walkup in the vtysh.
766 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
767 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
768 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
769 && vty
->node
> CONFIG_NODE
) {
770 vty
->node
= node_parent(vty
->node
);
771 ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
776 * If command succeeded in any other node than current (tried >
777 * 0) we have to move into node in the vtysh where it
780 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
781 || ret
== CMD_WARNING
) {
783 vty_out(vty
, "exit\n");
786 * If command didn't succeed in any node, continue with return
787 * value from first try.
791 vty
->node
= prev_node
;
794 cmd_free_strvec(vline
);
797 case CMD_WARNING_CONFIG_FAILED
:
798 if (vty
->type
== VTY_FILE
)
799 fprintf(stderr
, "line %d: Warning...: %s\n",
803 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
805 case CMD_ERR_AMBIGUOUS
:
806 fprintf(stderr
, "line %d: %% Ambiguous command: %s\n",
810 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
811 return CMD_ERR_AMBIGUOUS
;
812 case CMD_ERR_NO_MATCH
:
813 fprintf(stderr
, "line %d: %% Unknown command: %s\n",
817 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
818 return CMD_ERR_NO_MATCH
;
819 case CMD_ERR_INCOMPLETE
:
820 fprintf(stderr
, "line %d: %% Command incomplete: %s\n",
824 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
825 return CMD_ERR_INCOMPLETE
;
827 vty_out(vty
, "%s", vty
->buf
);
828 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
829 vty_out(vty
, "end\n");
831 case CMD_SUCCESS_DAEMON
: {
834 vty_out(vty
, "%s", vty
->buf
);
835 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
836 vty_out(vty
, "end\n");
837 cmd_stat
= vtysh_client_execute(&vtysh_client
[0],
839 if (cmd_stat
!= CMD_SUCCESS
)
843 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
847 /* This is the end */
848 vty_out(vty
, "\nend\n");
850 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
858 /* Configuration make from file. */
859 int vtysh_config_from_file(struct vty
*vty
, FILE *fp
)
862 const struct cmd_element
*cmd
;
864 /* once we have an error, we remember & return that */
865 int retcode
= CMD_SUCCESS
;
866 char *vty_buf_copy
= XCALLOC(MTYPE_VTYSH_CMD
, VTY_BUFSIZ
);
867 char *vty_buf_trimmed
= NULL
;
869 while (fgets(vty
->buf
, VTY_BUFSIZ
, fp
)) {
872 strlcpy(vty_buf_copy
, vty
->buf
, VTY_BUFSIZ
);
873 vty_buf_trimmed
= trim(vty_buf_copy
);
876 * Ignore the "end" lines, we will generate these where
877 * appropriate, otherwise we never execute
878 * XFRR_end_configuration, and start/end markers do not work.
880 if (strmatch(vty_buf_trimmed
, "end"))
883 ret
= command_config_read_one_line(vty
, &cmd
, lineno
, 1);
887 case CMD_WARNING_CONFIG_FAILED
:
888 if (vty
->type
== VTY_FILE
)
889 fprintf(stderr
, "line %d: Warning[%d]...: %s\n",
890 lineno
, vty
->node
, vty
->buf
);
894 case CMD_ERR_AMBIGUOUS
:
896 "line %d: %% Ambiguous command[%d]: %s\n",
897 lineno
, vty
->node
, vty
->buf
);
898 retcode
= CMD_ERR_AMBIGUOUS
;
900 case CMD_ERR_NO_MATCH
:
901 fprintf(stderr
, "line %d: %% Unknown command[%d]: %s",
902 lineno
, vty
->node
, vty
->buf
);
903 retcode
= CMD_ERR_NO_MATCH
;
905 case CMD_ERR_INCOMPLETE
:
907 "line %d: %% Command incomplete[%d]: %s\n",
908 lineno
, vty
->node
, vty
->buf
);
909 retcode
= CMD_ERR_INCOMPLETE
;
911 case CMD_SUCCESS_DAEMON
: {
913 int cmd_stat
= CMD_SUCCESS
;
915 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
916 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
917 cmd_stat
= vtysh_client_execute(
918 &vtysh_client
[i
], vty
->buf
);
920 * CMD_WARNING - Can mean that the
921 * command was parsed successfully but
922 * it was already entered in a few
923 * spots. As such if we receive a
924 * CMD_WARNING from a daemon we
925 * shouldn't stop talking to the other
926 * daemons for the particular command.
928 if (cmd_stat
!= CMD_SUCCESS
929 && cmd_stat
!= CMD_WARNING
) {
931 "line %d: Failure to communicate[%d] to %s, line: %s\n",
933 vtysh_client
[i
].name
,
940 if (cmd_stat
!= CMD_SUCCESS
)
944 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
949 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
955 * Function processes cli commands terminated with '?' character when entered
956 * through either 'vtysh' or 'vtysh -c' interfaces.
958 static int vtysh_process_questionmark(const char *input
, int input_len
)
962 vector vline
, describe
;
963 struct cmd_token
*token
;
968 vline
= cmd_make_strvec(input
);
970 /* In case of '> ?'. */
972 vline
= vector_init(1);
973 vector_set(vline
, NULL
);
974 } else if (input_len
&& isspace((unsigned char)input
[input_len
- 1]))
975 vector_set(vline
, NULL
);
977 describe
= cmd_describe_command(vline
, vty
, &ret
);
979 /* Ambiguous and no match error. */
981 case CMD_ERR_AMBIGUOUS
:
982 cmd_free_strvec(vline
);
983 vector_free(describe
);
984 vty_out(vty
, "%% Ambiguous command.\n");
987 case CMD_ERR_NO_MATCH
:
988 cmd_free_strvec(vline
);
990 vector_free(describe
);
991 vty_out(vty
, "%% There is no matched command.\n");
996 /* Get width of command string. */
998 for (i
= 0; i
< vector_active(describe
); i
++)
999 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1000 if (token
->text
[0] == '\0')
1003 int len
= strlen(token
->text
);
1009 for (i
= 0; i
< vector_active(describe
); i
++)
1010 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1012 vty_out(vty
, " %-s\n", token
->text
);
1014 vty_out(vty
, " %-*s %s\n", width
, token
->text
,
1017 if (IS_VARYING_TOKEN(token
->type
)) {
1018 const char *ref
= vector_slot(
1019 vline
, vector_active(vline
) - 1);
1021 vector varcomps
= vector_init(VECTOR_MIN_SIZE
);
1022 cmd_variable_complete(token
, ref
, varcomps
);
1024 if (vector_active(varcomps
) > 0) {
1026 rl_get_screen_size(&rows
, &cols
);
1028 char *ac
= cmd_variable_comp2str(
1030 vty_out(vty
, "%s\n", ac
);
1031 XFREE(MTYPE_TMP
, ac
);
1034 vector_free(varcomps
);
1038 cmd_free_strvec(vline
);
1039 vector_free(describe
);
1045 * Entry point for user commands terminated with '?' character and typed through
1046 * the usual vtysh's stdin interface. This is the function being registered with
1049 static int vtysh_rl_describe(int a
, int b
)
1055 ret
= vtysh_process_questionmark(rl_line_buffer
, rl_end
);
1062 * Function in charged of processing vtysh instructions terminating with '?'
1063 * character and received through the 'vtysh -c' interface. If user's
1064 * instruction is well-formatted, we will call the same processing routine
1065 * utilized by the traditional vtysh's stdin interface.
1067 int vtysh_execute_command_questionmark(char *input
)
1069 int input_len
, qmark_count
= 0;
1072 if (!(input
&& *input
))
1075 /* Finding out question_mark count and strlen */
1076 for (str
= input
; *str
; ++str
) {
1080 input_len
= str
- input
;
1083 * Verify that user's input terminates in '?' and that patterns such as
1084 * 'cmd ? subcmd ?' are prevented.
1086 if (qmark_count
!= 1 || input
[input_len
- 1] != '?')
1090 * Questionmark-processing function is not expecting to receive '?'
1091 * character in input string.
1093 input
[input_len
- 1] = '\0';
1095 return vtysh_process_questionmark(input
, input_len
- 1);
1098 /* Result of cmd_complete_command() call will be stored here
1099 * and used in new_completion() in order to put the space in
1100 * correct places only. */
1101 int complete_status
;
1103 static char *command_generator(const char *text
, int state
)
1106 static char **matched
= NULL
;
1107 static int index
= 0;
1113 if (vty
->node
== AUTH_NODE
|| vty
->node
== AUTH_ENABLE_NODE
)
1116 vline
= cmd_make_strvec(rl_line_buffer
);
1121 isspace((unsigned char)rl_line_buffer
[rl_end
- 1]))
1122 vector_set(vline
, NULL
);
1124 matched
= cmd_complete_command(vline
, vty
, &complete_status
);
1125 cmd_free_strvec(vline
);
1128 if (matched
&& matched
[index
]) {
1129 XCOUNTFREE(MTYPE_COMPLETION
, matched
[index
]);
1130 return matched
[index
++];
1133 XFREE(MTYPE_TMP
, matched
);
1138 static char **new_completion(const char *text
, int start
, int end
)
1142 matches
= rl_completion_matches(text
, command_generator
);
1146 if (complete_status
!= CMD_COMPLETE_FULL_MATCH
)
1147 /* only append a space on full match */
1148 rl_completion_append_character
= '\0';
1154 /* Vty node structures. */
1156 static struct cmd_node bgp_node
= {
1159 .parent_node
= CONFIG_NODE
,
1160 .prompt
= "%s(config-router)# ",
1162 #endif /* HAVE_BGPD */
1164 static struct cmd_node rip_node
= {
1167 .parent_node
= CONFIG_NODE
,
1168 .prompt
= "%s(config-router)# ",
1172 static struct cmd_node isis_node
= {
1175 .parent_node
= CONFIG_NODE
,
1176 .prompt
= "%s(config-router)# ",
1178 #endif /* HAVE_ISISD */
1181 static struct cmd_node openfabric_node
= {
1182 .name
= "openfabric",
1183 .node
= OPENFABRIC_NODE
,
1184 .parent_node
= CONFIG_NODE
,
1185 .prompt
= "%s(config-router)# ",
1187 #endif /* HAVE_FABRICD */
1189 static struct cmd_node interface_node
= {
1190 .name
= "interface",
1191 .node
= INTERFACE_NODE
,
1192 .parent_node
= CONFIG_NODE
,
1193 .prompt
= "%s(config-if)# ",
1196 static struct cmd_node pw_node
= {
1199 .parent_node
= CONFIG_NODE
,
1200 .prompt
= "%s(config-pw)# ",
1203 static struct cmd_node segment_routing_node
= {
1204 .name
= "segment-routing",
1205 .node
= SEGMENT_ROUTING_NODE
,
1206 .parent_node
= CONFIG_NODE
,
1207 .prompt
= "%s(config-sr)# ",
1210 #if defined(HAVE_PATHD)
1211 static struct cmd_node sr_traffic_eng_node
= {
1212 .name
= "sr traffic-eng",
1213 .node
= SR_TRAFFIC_ENG_NODE
,
1214 .parent_node
= SEGMENT_ROUTING_NODE
,
1215 .prompt
= "%s(config-sr-te)# ",
1218 static struct cmd_node srte_segment_list_node
= {
1219 .name
= "srte segment-list",
1220 .node
= SR_SEGMENT_LIST_NODE
,
1221 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1222 .prompt
= "%s(config-sr-te-segment-list)# ",
1225 static struct cmd_node srte_policy_node
= {
1226 .name
= "srte policy",
1227 .node
= SR_POLICY_NODE
,
1228 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1229 .prompt
= "%s(config-sr-te-policy)# ",
1232 static struct cmd_node srte_candidate_dyn_node
= {
1233 .name
= "srte candidate-dyn",
1234 .node
= SR_CANDIDATE_DYN_NODE
,
1235 .parent_node
= SR_POLICY_NODE
,
1236 .prompt
= "%s(config-sr-te-candidate)# ",
1239 static struct cmd_node pcep_node
= {
1240 .name
= "srte pcep",
1242 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1243 .prompt
= "%s(config-sr-te-pcep)# "
1246 static struct cmd_node pcep_pcc_node
= {
1247 .name
= "srte pcep pcc",
1248 .node
= PCEP_PCC_NODE
,
1249 .parent_node
= PCEP_NODE
,
1250 .prompt
= "%s(config-sr-te-pcep-pcc)# ",
1253 static struct cmd_node pcep_pce_node
= {
1254 .name
= "srte pcep pce-peer",
1255 .node
= PCEP_PCE_NODE
,
1256 .parent_node
= PCEP_NODE
,
1257 .prompt
= "%s(config-sr-te-pcep-pce-peer)# ",
1260 static struct cmd_node pcep_pce_config_node
= {
1261 .name
= "srte pcep pce-config",
1262 .node
= PCEP_PCE_CONFIG_NODE
,
1263 .parent_node
= PCEP_NODE
,
1264 .prompt
= "%s(pcep-sr-te-pcep-pce-config)# ",
1266 #endif /* HAVE_PATHD */
1268 static struct cmd_node vrf_node
= {
1271 .parent_node
= CONFIG_NODE
,
1272 .prompt
= "%s(config-vrf)# ",
1275 static struct cmd_node nh_group_node
= {
1276 .name
= "nexthop-group",
1277 .node
= NH_GROUP_NODE
,
1278 .parent_node
= CONFIG_NODE
,
1279 .prompt
= "%s(config-nh-group)# ",
1282 static struct cmd_node rmap_node
= {
1285 .parent_node
= CONFIG_NODE
,
1286 .prompt
= "%s(config-route-map)# ",
1289 static struct cmd_node srv6_node
= {
1292 .parent_node
= SEGMENT_ROUTING_NODE
,
1293 .prompt
= "%s(config-srv6)# ",
1296 static struct cmd_node srv6_locs_node
= {
1297 .name
= "srv6-locators",
1298 .node
= SRV6_LOCS_NODE
,
1299 .parent_node
= SRV6_NODE
,
1300 .prompt
= "%s(config-srv6-locators)# ",
1303 static struct cmd_node srv6_loc_node
= {
1304 .name
= "srv6-locator",
1305 .node
= SRV6_LOC_NODE
,
1306 .parent_node
= SRV6_LOCS_NODE
,
1307 .prompt
= "%s(config-srv6-locator)# ",
1311 static struct cmd_node pbr_map_node
= {
1313 .node
= PBRMAP_NODE
,
1314 .parent_node
= CONFIG_NODE
,
1315 .prompt
= "%s(config-pbr-map)# ",
1317 #endif /* HAVE_PBRD */
1319 static struct cmd_node zebra_node
= {
1322 .parent_node
= CONFIG_NODE
,
1323 .prompt
= "%s(config-router)# ",
1327 static struct cmd_node bgp_vpnv4_node
= {
1328 .name
= "bgp vpnv4",
1329 .node
= BGP_VPNV4_NODE
,
1330 .parent_node
= BGP_NODE
,
1331 .prompt
= "%s(config-router-af)# ",
1335 static struct cmd_node bgp_vpnv6_node
= {
1336 .name
= "bgp vpnv6",
1337 .node
= BGP_VPNV6_NODE
,
1338 .parent_node
= BGP_NODE
,
1339 .prompt
= "%s(config-router-af)# ",
1343 static struct cmd_node bgp_flowspecv4_node
= {
1344 .name
= "bgp ipv4 flowspec",
1345 .node
= BGP_FLOWSPECV4_NODE
,
1346 .parent_node
= BGP_NODE
,
1347 .prompt
= "%s(config-router-af)# ",
1351 static struct cmd_node bgp_flowspecv6_node
= {
1352 .name
= "bgp ipv6 flowspec",
1353 .node
= BGP_FLOWSPECV6_NODE
,
1354 .parent_node
= BGP_NODE
,
1355 .prompt
= "%s(config-router-af)# ",
1359 static struct cmd_node bgp_ipv4_node
= {
1360 .name
= "bgp ipv4 unicast",
1361 .node
= BGP_IPV4_NODE
,
1362 .parent_node
= BGP_NODE
,
1363 .prompt
= "%s(config-router-af)# ",
1367 static struct cmd_node bgp_ipv4m_node
= {
1368 .name
= "bgp ipv4 multicast",
1369 .node
= BGP_IPV4M_NODE
,
1370 .parent_node
= BGP_NODE
,
1371 .prompt
= "%s(config-router-af)# ",
1375 static struct cmd_node bgp_ipv4l_node
= {
1376 .name
= "bgp ipv4 labeled unicast",
1377 .node
= BGP_IPV4L_NODE
,
1378 .parent_node
= BGP_NODE
,
1379 .prompt
= "%s(config-router-af)# ",
1383 static struct cmd_node bgp_ipv6_node
= {
1385 .node
= BGP_IPV6_NODE
,
1386 .parent_node
= BGP_NODE
,
1387 .prompt
= "%s(config-router-af)# ",
1391 static struct cmd_node bgp_ipv6m_node
= {
1392 .name
= "bgp ipv6 multicast",
1393 .node
= BGP_IPV6M_NODE
,
1394 .parent_node
= BGP_NODE
,
1395 .prompt
= "%s(config-router-af)# ",
1399 static struct cmd_node bgp_evpn_node
= {
1401 .node
= BGP_EVPN_NODE
,
1402 .parent_node
= BGP_NODE
,
1403 .prompt
= "%s(config-router-af)# ",
1407 static struct cmd_node bgp_evpn_vni_node
= {
1408 .name
= "bgp evpn vni",
1409 .node
= BGP_EVPN_VNI_NODE
,
1410 .parent_node
= BGP_EVPN_NODE
,
1411 .prompt
= "%s(config-router-af-vni)# ",
1414 static struct cmd_node bgp_ipv6l_node
= {
1415 .name
= "bgp ipv6 labeled unicast",
1416 .node
= BGP_IPV6L_NODE
,
1417 .parent_node
= BGP_NODE
,
1418 .prompt
= "%s(config-router-af)# ",
1422 #ifdef ENABLE_BGP_VNC
1423 static struct cmd_node bgp_vnc_defaults_node
= {
1424 .name
= "bgp vnc defaults",
1425 .node
= BGP_VNC_DEFAULTS_NODE
,
1426 .parent_node
= BGP_NODE
,
1427 .prompt
= "%s(config-router-vnc-defaults)# ",
1430 static struct cmd_node bgp_vnc_nve_group_node
= {
1431 .name
= "bgp vnc nve",
1432 .node
= BGP_VNC_NVE_GROUP_NODE
,
1433 .parent_node
= BGP_NODE
,
1434 .prompt
= "%s(config-router-vnc-nve-group)# ",
1437 static struct cmd_node bgp_vrf_policy_node
= {
1438 .name
= "bgp vrf policy",
1439 .node
= BGP_VRF_POLICY_NODE
,
1440 .parent_node
= BGP_NODE
,
1441 .prompt
= "%s(config-router-vrf-policy)# ",
1444 static struct cmd_node bgp_vnc_l2_group_node
= {
1445 .name
= "bgp vnc l2",
1446 .node
= BGP_VNC_L2_GROUP_NODE
,
1447 .parent_node
= BGP_NODE
,
1448 .prompt
= "%s(config-router-vnc-l2-group)# ",
1450 #endif /* ENABLE_BGP_VNC */
1452 static struct cmd_node bmp_node
= {
1455 .parent_node
= BGP_NODE
,
1456 .prompt
= "%s(config-bgp-bmp)# "
1459 static struct cmd_node bgp_srv6_node
= {
1461 .node
= BGP_SRV6_NODE
,
1462 .parent_node
= BGP_NODE
,
1463 .prompt
= "%s(config-router-srv6)# ",
1465 #endif /* HAVE_BGPD */
1468 static struct cmd_node ospf_node
= {
1471 .parent_node
= CONFIG_NODE
,
1472 .prompt
= "%s(config-router)# ",
1474 #endif /* HAVE_OSPFD */
1477 static struct cmd_node eigrp_node
= {
1480 .parent_node
= CONFIG_NODE
,
1481 .prompt
= "%s(config-router)# ",
1483 #endif /* HAVE_EIGRPD */
1486 static struct cmd_node babel_node
= {
1489 .parent_node
= CONFIG_NODE
,
1490 .prompt
= "%s(config-router)# ",
1492 #endif /* HAVE_BABELD */
1494 static struct cmd_node ripng_node
= {
1497 .parent_node
= CONFIG_NODE
,
1498 .prompt
= "%s(config-router)# ",
1502 static struct cmd_node ospf6_node
= {
1505 .parent_node
= CONFIG_NODE
,
1506 .prompt
= "%s(config-ospf6)# ",
1508 #endif /* HAVE_OSPF6D */
1511 static struct cmd_node ldp_node
= {
1514 .parent_node
= CONFIG_NODE
,
1515 .prompt
= "%s(config-ldp)# ",
1518 static struct cmd_node ldp_ipv4_node
= {
1520 .node
= LDP_IPV4_NODE
,
1521 .parent_node
= LDP_NODE
,
1522 .prompt
= "%s(config-ldp-af)# ",
1525 static struct cmd_node ldp_ipv6_node
= {
1527 .node
= LDP_IPV6_NODE
,
1528 .parent_node
= LDP_NODE
,
1529 .prompt
= "%s(config-ldp-af)# ",
1532 static struct cmd_node ldp_ipv4_iface_node
= {
1533 .name
= "ldp ipv4 interface",
1534 .node
= LDP_IPV4_IFACE_NODE
,
1535 .parent_node
= LDP_IPV4_NODE
,
1536 .prompt
= "%s(config-ldp-af-if)# ",
1539 static struct cmd_node ldp_ipv6_iface_node
= {
1540 .name
= "ldp ipv6 interface",
1541 .node
= LDP_IPV6_IFACE_NODE
,
1542 .parent_node
= LDP_IPV6_NODE
,
1543 .prompt
= "%s(config-ldp-af-if)# ",
1546 static struct cmd_node ldp_l2vpn_node
= {
1547 .name
= "ldp l2vpn",
1548 .node
= LDP_L2VPN_NODE
,
1549 .parent_node
= CONFIG_NODE
,
1550 .prompt
= "%s(config-l2vpn)# ",
1553 static struct cmd_node ldp_pseudowire_node
= {
1555 .node
= LDP_PSEUDOWIRE_NODE
,
1556 .parent_node
= LDP_L2VPN_NODE
,
1557 .prompt
= "%s(config-l2vpn-pw)# ",
1559 #endif /* HAVE_LDPD */
1561 static struct cmd_node keychain_node
= {
1563 .node
= KEYCHAIN_NODE
,
1564 .parent_node
= CONFIG_NODE
,
1565 .prompt
= "%s(config-keychain)# ",
1568 static struct cmd_node keychain_key_node
= {
1569 .name
= "keychain key",
1570 .node
= KEYCHAIN_KEY_NODE
,
1571 .parent_node
= KEYCHAIN_NODE
,
1572 .prompt
= "%s(config-keychain-key)# ",
1575 struct cmd_node link_params_node
= {
1576 .name
= "link-params",
1577 .node
= LINK_PARAMS_NODE
,
1578 .parent_node
= INTERFACE_NODE
,
1579 .prompt
= "%s(config-link-params)# ",
1584 static struct cmd_node rpki_node
= {
1587 .parent_node
= CONFIG_NODE
,
1588 .prompt
= "%s(config-rpki)# ",
1590 #endif /* HAVE_BGPD */
1593 static struct cmd_node bfd_node
= {
1596 .parent_node
= CONFIG_NODE
,
1597 .prompt
= "%s(config-bfd)# ",
1600 static struct cmd_node bfd_peer_node
= {
1602 .node
= BFD_PEER_NODE
,
1603 .parent_node
= BFD_NODE
,
1604 .prompt
= "%s(config-bfd-peer)# ",
1607 static struct cmd_node bfd_profile_node
= {
1608 .name
= "bfd profile",
1609 .node
= BFD_PROFILE_NODE
,
1610 .parent_node
= BFD_NODE
,
1611 .prompt
= "%s(config-bfd-profile)# ",
1613 #endif /* HAVE_BFDD */
1615 /* Defined in lib/vty.c */
1616 extern struct cmd_node vty_node
;
1618 /* When '^Z' is received from vty, move down to the enable mode. */
1619 static int vtysh_end(void)
1621 switch (vty
->node
) {
1624 /* Nothing to do. */
1627 vty
->node
= ENABLE_NODE
;
1633 #include "vtysh/vtysh_clippy.c"
1635 DEFUNSH(VTYSH_REALLYALL
, vtysh_end_all
, vtysh_end_all_cmd
, "end",
1636 "End current mode and change to enable mode\n")
1641 DEFUNSH(VTYSH_ZEBRA
, srv6
, srv6_cmd
,
1643 "Segment-Routing SRv6 configuration\n")
1645 vty
->node
= SRV6_NODE
;
1649 DEFUNSH(VTYSH_ZEBRA
, srv6_locators
, srv6_locators_cmd
,
1651 "Segment-Routing SRv6 locators configuration\n")
1653 vty
->node
= SRV6_LOCS_NODE
;
1657 DEFUNSH(VTYSH_ZEBRA
, srv6_locator
, srv6_locator_cmd
,
1659 "Segment Routing SRv6 locator\n"
1660 "Specify locator-name\n")
1662 vty
->node
= SRV6_LOC_NODE
;
1667 DEFUNSH(VTYSH_BGPD
, router_bgp
, router_bgp_cmd
,
1668 "router bgp [ASNUM [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]",
1669 ROUTER_STR BGP_STR AS_STR
1670 "BGP view\nBGP VRF\n"
1672 "Force the AS notation output\n"
1673 "use 'AA.BB' format for AS 4 byte values\n"
1674 "use 'AA.BB' format for all AS values\n"
1675 "use plain format for all AS values\n")
1677 vty
->node
= BGP_NODE
;
1681 #ifdef KEEP_OLD_VPN_COMMANDS
1682 DEFUNSH(VTYSH_BGPD
, address_family_vpnv4
, address_family_vpnv4_cmd
,
1683 "address-family vpnv4 [unicast]",
1684 "Enter Address Family command mode\n"
1686 BGP_AF_MODIFIER_STR
)
1688 vty
->node
= BGP_VPNV4_NODE
;
1692 DEFUNSH(VTYSH_BGPD
, address_family_vpnv6
, address_family_vpnv6_cmd
,
1693 "address-family vpnv6 [unicast]",
1694 "Enter Address Family command mode\n"
1696 BGP_AF_MODIFIER_STR
)
1698 vty
->node
= BGP_VPNV6_NODE
;
1701 #endif /* KEEP_OLD_VPN_COMMANDS */
1703 DEFUNSH(VTYSH_BGPD
, address_family_ipv4
, address_family_ipv4_cmd
,
1704 "address-family ipv4 [unicast]",
1705 "Enter Address Family command mode\n"
1707 BGP_AF_MODIFIER_STR
)
1709 vty
->node
= BGP_IPV4_NODE
;
1713 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv4
, address_family_flowspecv4_cmd
,
1714 "address-family ipv4 flowspec",
1715 "Enter Address Family command mode\n"
1717 BGP_AF_MODIFIER_STR
)
1719 vty
->node
= BGP_FLOWSPECV4_NODE
;
1723 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv6
, address_family_flowspecv6_cmd
,
1724 "address-family ipv6 flowspec",
1725 "Enter Address Family command mode\n"
1727 BGP_AF_MODIFIER_STR
)
1729 vty
->node
= BGP_FLOWSPECV6_NODE
;
1733 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_multicast
,
1734 address_family_ipv4_multicast_cmd
, "address-family ipv4 multicast",
1735 "Enter Address Family command mode\n"
1737 BGP_AF_MODIFIER_STR
)
1739 vty
->node
= BGP_IPV4M_NODE
;
1743 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_vpn
, address_family_ipv4_vpn_cmd
,
1744 "address-family ipv4 vpn",
1745 "Enter Address Family command mode\n"
1747 BGP_AF_MODIFIER_STR
)
1749 vty
->node
= BGP_VPNV4_NODE
;
1753 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_labeled_unicast
,
1754 address_family_ipv4_labeled_unicast_cmd
,
1755 "address-family ipv4 labeled-unicast",
1756 "Enter Address Family command mode\n"
1758 BGP_AF_MODIFIER_STR
)
1760 vty
->node
= BGP_IPV4L_NODE
;
1764 DEFUNSH(VTYSH_BGPD
, address_family_ipv6
, address_family_ipv6_cmd
,
1765 "address-family ipv6 [unicast]",
1766 "Enter Address Family command mode\n"
1768 BGP_AF_MODIFIER_STR
)
1770 vty
->node
= BGP_IPV6_NODE
;
1774 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_multicast
,
1775 address_family_ipv6_multicast_cmd
, "address-family ipv6 multicast",
1776 "Enter Address Family command mode\n"
1778 BGP_AF_MODIFIER_STR
)
1780 vty
->node
= BGP_IPV6M_NODE
;
1784 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_vpn
, address_family_ipv6_vpn_cmd
,
1785 "address-family ipv6 vpn",
1786 "Enter Address Family command mode\n"
1788 BGP_AF_MODIFIER_STR
)
1790 vty
->node
= BGP_VPNV6_NODE
;
1794 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_labeled_unicast
,
1795 address_family_ipv6_labeled_unicast_cmd
,
1796 "address-family ipv6 labeled-unicast",
1797 "Enter Address Family command mode\n"
1799 BGP_AF_MODIFIER_STR
)
1801 vty
->node
= BGP_IPV6L_NODE
;
1809 "Enable rpki and enter rpki configuration mode\n")
1811 vty
->node
= RPKI_NODE
;
1818 "bmp targets BMPTARGETS",
1819 "BGP Monitoring Protocol\n"
1820 "Create BMP target group\n"
1821 "Name of the BMP target group\n")
1823 vty
->node
= BMP_NODE
;
1830 "segment-routing srv6",
1831 "Segment-Routing configuration\n"
1832 "Segment-Routing SRv6 configuration\n")
1834 vty
->node
= BGP_SRV6_NODE
;
1842 "exit Segment-Routing SRv6 configuration\n")
1844 if (vty
->node
== BGP_SRV6_NODE
)
1845 vty
->node
= BGP_NODE
;
1853 "quit Segment-Routing SRv6 configuration\n")
1855 if (vty
->node
== BGP_SRV6_NODE
)
1856 vty
->node
= BGP_NODE
;
1860 DEFUNSH(VTYSH_BGPD
, address_family_evpn
, address_family_evpn_cmd
,
1861 "address-family <l2vpn evpn>",
1862 "Enter Address Family command mode\n"
1864 BGP_AF_MODIFIER_STR
)
1866 vty
->node
= BGP_EVPN_NODE
;
1870 DEFUNSH(VTYSH_BGPD
, bgp_evpn_vni
, bgp_evpn_vni_cmd
, "vni " CMD_VNI_RANGE
,
1871 "VXLAN Network Identifier\n"
1874 vty
->node
= BGP_EVPN_VNI_NODE
;
1878 #if defined(ENABLE_BGP_VNC)
1879 DEFUNSH(VTYSH_BGPD
, vnc_defaults
, vnc_defaults_cmd
, "vnc defaults",
1880 "VNC/RFP related configuration\n"
1881 "Configure default NVE group\n")
1883 vty
->node
= BGP_VNC_DEFAULTS_NODE
;
1887 DEFUNSH(VTYSH_BGPD
, vnc_nve_group
, vnc_nve_group_cmd
, "vnc nve-group NAME",
1888 "VNC/RFP related configuration\n"
1889 "Configure a NVE group\n"
1892 vty
->node
= BGP_VNC_NVE_GROUP_NODE
;
1896 DEFUNSH(VTYSH_BGPD
, vnc_vrf_policy
, vnc_vrf_policy_cmd
, "vrf-policy NAME",
1897 "Configure a VRF policy group\n"
1900 vty
->node
= BGP_VRF_POLICY_NODE
;
1904 DEFUNSH(VTYSH_BGPD
, vnc_l2_group
, vnc_l2_group_cmd
, "vnc l2-group NAME",
1905 "VNC/RFP related configuration\n"
1906 "Configure a L2 group\n"
1909 vty
->node
= BGP_VNC_L2_GROUP_NODE
;
1913 DEFUNSH(VTYSH_BGPD
, exit_vnc_config
, exit_vnc_config_cmd
, "exit-vnc",
1914 "Exit from VNC configuration mode\n")
1916 if (vty
->node
== BGP_VNC_DEFAULTS_NODE
1917 || vty
->node
== BGP_VNC_NVE_GROUP_NODE
1918 || vty
->node
== BGP_VNC_L2_GROUP_NODE
)
1919 vty
->node
= BGP_NODE
;
1923 DEFUNSH(VTYSH_BGPD
, exit_vrf_policy
, exit_vrf_policy_cmd
, "exit-vrf-policy",
1924 "Exit from VRF policy configuration mode\n")
1926 if (vty
->node
== BGP_VRF_POLICY_NODE
)
1927 vty
->node
= BGP_NODE
;
1931 #endif /* HAVE_BGPD */
1933 DEFUNSH(VTYSH_KEYS
, key_chain
, key_chain_cmd
, "key chain WORD",
1934 "Authentication key management\n"
1935 "Key-chain management\n"
1938 vty
->node
= KEYCHAIN_NODE
;
1942 DEFUNSH(VTYSH_KEYS
, key
, key_cmd
, "key (0-2147483647)",
1944 "Key identifier number\n")
1946 vty
->node
= KEYCHAIN_KEY_NODE
;
1951 DEFUNSH(VTYSH_RIPD
, router_rip
, router_rip_cmd
, "router rip [vrf NAME]",
1952 ROUTER_STR
"RIP\n" VRF_CMD_HELP_STR
)
1954 vty
->node
= RIP_NODE
;
1957 #endif /* HAVE_RIPD */
1960 DEFUNSH(VTYSH_RIPNGD
, router_ripng
, router_ripng_cmd
, "router ripng [vrf NAME]",
1961 ROUTER_STR
"RIPng\n" VRF_CMD_HELP_STR
)
1963 vty
->node
= RIPNG_NODE
;
1966 #endif /* HAVE_RIPNGD */
1969 DEFUNSH(VTYSH_OSPFD
, router_ospf
, router_ospf_cmd
,
1970 "router ospf [(1-65535)] [vrf NAME]",
1971 "Enable a routing process\n"
1972 "Start OSPF configuration\n"
1976 vty
->node
= OSPF_NODE
;
1979 #endif /* HAVE_OSPFD */
1982 DEFUNSH(VTYSH_EIGRPD
, router_eigrp
, router_eigrp_cmd
, "router eigrp (1-65535) [vrf NAME]",
1983 "Enable a routing process\n"
1984 "Start EIGRP configuration\n"
1985 "AS number to use\n"
1988 vty
->node
= EIGRP_NODE
;
1991 #endif /* HAVE_EIGRPD */
1994 DEFUNSH(VTYSH_BABELD
, router_babel
, router_babel_cmd
, "router babel",
1995 "Enable a routing process\n"
1996 "Make Babel instance command\n")
1998 vty
->node
= BABEL_NODE
;
2001 #endif /* HAVE_BABELD */
2004 DEFUNSH(VTYSH_OSPF6D
, router_ospf6
, router_ospf6_cmd
, "router ospf6 [vrf NAME]",
2005 ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR
)
2007 vty
->node
= OSPF6_NODE
;
2012 #if defined(HAVE_LDPD)
2013 DEFUNSH(VTYSH_LDPD
, ldp_mpls_ldp
, ldp_mpls_ldp_cmd
, "mpls ldp",
2014 "Global MPLS configuration subcommands\n"
2015 "Label Distribution Protocol\n")
2017 vty
->node
= LDP_NODE
;
2021 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv4
, ldp_address_family_ipv4_cmd
,
2022 "address-family ipv4",
2023 "Configure Address Family and its parameters\n"
2026 vty
->node
= LDP_IPV4_NODE
;
2030 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv6
, ldp_address_family_ipv6_cmd
,
2031 "address-family ipv6",
2032 "Configure Address Family and its parameters\n"
2035 vty
->node
= LDP_IPV6_NODE
;
2039 DEFUNSH(VTYSH_LDPD
, ldp_exit_address_family
, ldp_exit_address_family_cmd
,
2040 "exit-address-family", "Exit from Address Family configuration mode\n")
2042 if (vty
->node
== LDP_IPV4_NODE
|| vty
->node
== LDP_IPV6_NODE
)
2043 vty
->node
= LDP_NODE
;
2047 DEFUNSH(VTYSH_LDPD
, ldp_interface_ifname
, ldp_interface_ifname_cmd
,
2049 "Enable LDP on an interface and enter interface submode\n"
2050 "Interface's name\n")
2052 switch (vty
->node
) {
2054 vty
->node
= LDP_IPV4_IFACE_NODE
;
2057 vty
->node
= LDP_IPV6_IFACE_NODE
;
2066 DEFUNSH(VTYSH_LDPD
, ldp_l2vpn_word_type_vpls
, ldp_l2vpn_word_type_vpls_cmd
,
2067 "l2vpn WORD type vpls",
2068 "Configure l2vpn commands\n"
2071 "Virtual Private LAN Service\n")
2073 vty
->node
= LDP_L2VPN_NODE
;
2077 DEFUNSH(VTYSH_LDPD
, ldp_member_pseudowire_ifname
,
2078 ldp_member_pseudowire_ifname_cmd
, "member pseudowire IFNAME",
2079 "L2VPN member configuration\n"
2080 "Pseudowire interface\n"
2081 "Interface's name\n")
2083 vty
->node
= LDP_PSEUDOWIRE_NODE
;
2089 DEFUNSH(VTYSH_ISISD
, router_isis
, router_isis_cmd
,
2090 "router isis WORD [vrf NAME]",
2093 "ISO Routing area tag\n" VRF_CMD_HELP_STR
)
2095 vty
->node
= ISIS_NODE
;
2098 #endif /* HAVE_ISISD */
2101 DEFUNSH(VTYSH_FABRICD
, router_openfabric
, router_openfabric_cmd
, "router openfabric WORD",
2103 "OpenFabric routing protocol\n"
2104 "ISO Routing area tag\n")
2106 vty
->node
= OPENFABRIC_NODE
;
2109 #endif /* HAVE_FABRICD */
2111 DEFUNSH(VTYSH_SR
, segment_routing
, segment_routing_cmd
,
2113 "Configure segment routing\n")
2115 vty
->node
= SEGMENT_ROUTING_NODE
;
2119 #if defined (HAVE_PATHD)
2120 DEFUNSH(VTYSH_PATHD
, sr_traffic_eng
, sr_traffic_eng_cmd
,
2122 "Configure SR traffic engineering\n")
2124 vty
->node
= SR_TRAFFIC_ENG_NODE
;
2128 DEFUNSH(VTYSH_PATHD
, srte_segment_list
, srte_segment_list_cmd
,
2129 "segment-list WORD$name",
2131 "Segment List Name\n")
2133 vty
->node
= SR_SEGMENT_LIST_NODE
;
2137 DEFUNSH(VTYSH_PATHD
, srte_policy
, srte_policy_cmd
,
2138 "policy color (0-4294967295) endpoint <A.B.C.D|X:X::X:X>",
2139 "Segment Routing Policy\n"
2141 "SR Policy color value\n"
2142 "SR Policy endpoint\n"
2143 "SR Policy endpoint IPv4 address\n"
2144 "SR Policy endpoint IPv6 address\n")
2146 vty
->node
= SR_POLICY_NODE
;
2150 DEFUNSH(VTYSH_PATHD
, srte_policy_candidate_dyn_path
,
2151 srte_policy_candidate_dyn_path_cmd
,
2152 "candidate-path preference (0-4294967295) name WORD dynamic",
2153 "Segment Routing Policy Candidate Path\n"
2154 "Segment Routing Policy Candidate Path Preference\n"
2155 "Administrative Preference\n"
2156 "Segment Routing Policy Candidate Path Name\n"
2160 vty
->node
= SR_CANDIDATE_DYN_NODE
;
2164 DEFUNSH(VTYSH_PATHD
, pcep
, pcep_cmd
,
2166 "Configure SR pcep\n")
2168 vty
->node
= PCEP_NODE
;
2172 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcc
, pcep_cli_pcc_cmd
,
2174 "PCC configuration\n")
2176 vty
->node
= PCEP_PCC_NODE
;
2180 DEFUNSH(VTYSH_PATHD
, pcep_cli_pce
, pcep_cli_pce_cmd
,
2182 "PCE configuration\n"
2185 vty
->node
= PCEP_PCE_NODE
;
2189 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcep_pce_config
, pcep_cli_pcep_pce_config_cmd
,
2191 "PCEP peer Configuration Group\n"
2192 "PCEP peer Configuration Group name\n")
2194 vty
->node
= PCEP_PCE_CONFIG_NODE
;
2198 #endif /* HAVE_PATHD */
2200 /* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
2201 DEFUNSH(VTYSH_AFFMAP
, affinity_map
, vtysh_affinity_map_cmd
,
2202 "affinity-map NAME bit-position (0-1023)",
2203 "Affinity map configuration\n"
2204 "Affinity attribute name\n"
2205 "Bit position for affinity attribute value\n"
2211 /* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
2212 DEFUNSH(VTYSH_AFFMAP
, no_affinity_map
, vtysh_no_affinity_map_cmd
,
2213 "no affinity-map NAME$name [bit-position (0-1023)$position]",
2215 "Affinity map configuration\n"
2216 "Affinity attribute name\n"
2217 "Bit position for affinity attribute value\n"
2223 DEFUNSH(VTYSH_RMAP
, vtysh_route_map
, vtysh_route_map_cmd
,
2224 "route-map RMAP_NAME <deny|permit> (1-65535)",
2225 "Create route-map or enter route-map command mode\n"
2227 "Route map denies set operations\n"
2228 "Route map permits set operations\n"
2229 "Sequence to insert to/delete from existing route-map entry\n")
2231 vty
->node
= RMAP_NODE
;
2236 DEFUNSH(VTYSH_PBRD
, vtysh_pbr_map
, vtysh_pbr_map_cmd
,
2237 "pbr-map PBRMAP seq (1-700)",
2238 "Create pbr-map or enter pbr-map command mode\n"
2239 "The name of the PBR MAP\n"
2240 "Sequence to insert to/delete from existing pbr-map entry\n"
2241 "Sequence number\n")
2243 vty
->node
= PBRMAP_NODE
;
2247 DEFSH(VTYSH_PBRD
, vtysh_no_pbr_map_cmd
, "no pbr-map PBRMAP [seq (1-700)]",
2250 "The name of the PBR MAP\n"
2251 "Sequence to delete from existing pbr-map entry\n"
2252 "Sequence number\n")
2253 #endif /* HAVE_PBRD */
2256 DEFUNSH(VTYSH_BFDD
, bfd_enter
, bfd_enter_cmd
, "bfd", "Configure BFD peers\n")
2258 vty
->node
= BFD_NODE
;
2262 DEFUNSH(VTYSH_BFDD
, bfd_peer_enter
, bfd_peer_enter_cmd
,
2263 "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
2265 "IPv4 peer address\n"
2266 "IPv6 peer address\n"
2267 "Configure multihop\n"
2268 "Configure local address\n"
2269 "IPv4 local address\n"
2270 "IPv6 local address\n"
2272 "Configure interface name to use\n"
2274 "Configure VRF name\n")
2276 vty
->node
= BFD_PEER_NODE
;
2280 DEFUNSH(VTYSH_BFDD
, bfd_profile_enter
, bfd_profile_enter_cmd
,
2283 BFD_PROFILE_NAME_STR
)
2285 vty
->node
= BFD_PROFILE_NODE
;
2288 #endif /* HAVE_BFDD */
2290 DEFUNSH(VTYSH_ALL
, vtysh_line_vty
, vtysh_line_vty_cmd
, "line vty",
2291 "Configure a terminal line\n"
2292 "Virtual terminal\n")
2294 vty
->node
= VTY_NODE
;
2298 DEFUNSH(VTYSH_REALLYALL
, vtysh_enable
, vtysh_enable_cmd
, "enable",
2299 "Turn on privileged mode command\n")
2301 vty
->node
= ENABLE_NODE
;
2305 DEFUNSH(VTYSH_REALLYALL
, vtysh_disable
, vtysh_disable_cmd
, "disable",
2306 "Turn off privileged mode command\n")
2308 if (vty
->node
== ENABLE_NODE
)
2309 vty
->node
= VIEW_NODE
;
2313 DEFUNSH(VTYSH_REALLYALL
, vtysh_config_terminal
, vtysh_config_terminal_cmd
,
2314 "configure [terminal]",
2315 "Configuration from vty interface\n"
2316 "Configuration terminal\n")
2318 vty
->node
= CONFIG_NODE
;
2322 static int vtysh_exit(struct vty
*vty
)
2324 struct cmd_node
*cnode
= vector_lookup(cmdvec
, vty
->node
);
2326 if (vty
->node
== VIEW_NODE
|| vty
->node
== ENABLE_NODE
)
2328 if (cnode
->node_exit
)
2329 cnode
->node_exit(vty
);
2330 if (cnode
->parent_node
)
2331 vty
->node
= cnode
->parent_node
;
2333 if (vty
->node
== CONFIG_NODE
) {
2334 /* resync in case one of the daemons is somewhere else */
2335 vtysh_execute("end");
2336 vtysh_execute("configure");
2341 DEFUNSH(VTYSH_REALLYALL
, vtysh_exit_all
, vtysh_exit_all_cmd
, "exit",
2342 "Exit current mode and down to previous mode\n")
2344 return vtysh_exit(vty
);
2347 DEFUNSH(VTYSH_REALLYALL
, vtysh_quit_all
, vtysh_quit_all_cmd
, "quit",
2348 "Exit current mode and down to previous mode\n")
2350 return vtysh_exit_all(self
, vty
, argc
, argv
);
2354 DEFUNSH(VTYSH_BGPD
, exit_address_family
, exit_address_family_cmd
,
2355 "exit-address-family", "Exit from Address Family configuration mode\n")
2357 if (vty
->node
== BGP_IPV4_NODE
|| vty
->node
== BGP_IPV4M_NODE
2358 || vty
->node
== BGP_IPV4L_NODE
|| vty
->node
== BGP_VPNV4_NODE
2359 || vty
->node
== BGP_VPNV6_NODE
|| vty
->node
== BGP_IPV6_NODE
2360 || vty
->node
== BGP_IPV6L_NODE
|| vty
->node
== BGP_IPV6M_NODE
2361 || vty
->node
== BGP_EVPN_NODE
2362 || vty
->node
== BGP_FLOWSPECV4_NODE
2363 || vty
->node
== BGP_FLOWSPECV6_NODE
)
2364 vty
->node
= BGP_NODE
;
2368 DEFUNSH(VTYSH_BGPD
, exit_vni
, exit_vni_cmd
, "exit-vni", "Exit from VNI mode\n")
2370 if (vty
->node
== BGP_EVPN_VNI_NODE
)
2371 vty
->node
= BGP_EVPN_NODE
;
2375 DEFUNSH(VTYSH_BGPD
, rpki_exit
, rpki_exit_cmd
, "exit",
2376 "Exit current mode and down to previous mode\n")
2382 DEFUNSH(VTYSH_BGPD
, rpki_quit
, rpki_quit_cmd
, "quit",
2383 "Exit current mode and down to previous mode\n")
2385 return rpki_exit(self
, vty
, argc
, argv
);
2388 DEFUNSH(VTYSH_BGPD
, bmp_exit
, bmp_exit_cmd
, "exit",
2389 "Exit current mode and down to previous mode\n")
2395 DEFUNSH(VTYSH_BGPD
, bmp_quit
, bmp_quit_cmd
, "quit",
2396 "Exit current mode and down to previous mode\n")
2398 return bmp_exit(self
, vty
, argc
, argv
);
2400 #endif /* HAVE_BGPD */
2402 DEFUNSH(VTYSH_VRF
, exit_vrf_config
, exit_vrf_config_cmd
, "exit-vrf",
2403 "Exit from VRF configuration mode\n")
2405 if (vty
->node
== VRF_NODE
)
2406 vty
->node
= CONFIG_NODE
;
2410 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_config
, exit_srv6_config_cmd
, "exit",
2411 "Exit from SRv6 configuration mode\n")
2413 if (vty
->node
== SRV6_NODE
)
2414 vty
->node
= SEGMENT_ROUTING_NODE
;
2418 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_locs_config
, exit_srv6_locs_config_cmd
, "exit",
2419 "Exit from SRv6-locator configuration mode\n")
2421 if (vty
->node
== SRV6_LOCS_NODE
)
2422 vty
->node
= SRV6_NODE
;
2426 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_loc_config
, exit_srv6_loc_config_cmd
, "exit",
2427 "Exit from SRv6-locators configuration mode\n")
2429 if (vty
->node
== SRV6_LOC_NODE
)
2430 vty
->node
= SRV6_LOCS_NODE
;
2435 DEFUNSH(VTYSH_RIPD
, vtysh_exit_ripd
, vtysh_exit_ripd_cmd
, "exit",
2436 "Exit current mode and down to previous mode\n")
2438 return vtysh_exit(vty
);
2441 DEFUNSH(VTYSH_RIPD
, vtysh_quit_ripd
, vtysh_quit_ripd_cmd
, "quit",
2442 "Exit current mode and down to previous mode\n")
2444 return vtysh_exit_ripd(self
, vty
, argc
, argv
);
2446 #endif /* HAVE_RIPD */
2449 DEFUNSH(VTYSH_RIPNGD
, vtysh_exit_ripngd
, vtysh_exit_ripngd_cmd
, "exit",
2450 "Exit current mode and down to previous mode\n")
2452 return vtysh_exit(vty
);
2455 DEFUNSH(VTYSH_RIPNGD
, vtysh_quit_ripngd
, vtysh_quit_ripngd_cmd
, "quit",
2456 "Exit current mode and down to previous mode\n")
2458 return vtysh_exit_ripngd(self
, vty
, argc
, argv
);
2460 #endif /* HAVE_RIPNGD */
2462 DEFUNSH(VTYSH_RMAP
, vtysh_exit_rmap
, vtysh_exit_rmap_cmd
, "exit",
2463 "Exit current mode and down to previous mode\n")
2465 return vtysh_exit(vty
);
2468 DEFUNSH(VTYSH_RMAP
, vtysh_quit_rmap
, vtysh_quit_rmap_cmd
, "quit",
2469 "Exit current mode and down to previous mode\n")
2471 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2475 DEFUNSH(VTYSH_PBRD
, vtysh_exit_pbr_map
, vtysh_exit_pbr_map_cmd
, "exit",
2476 "Exit current mode and down to previous mode\n")
2478 return vtysh_exit(vty
);
2481 DEFUNSH(VTYSH_PBRD
, vtysh_quit_pbr_map
, vtysh_quit_pbr_map_cmd
, "quit",
2482 "Exit current mode and down to previous mode\n")
2484 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2486 #endif /* HAVE_PBRD */
2489 DEFUNSH(VTYSH_BGPD
, vtysh_exit_bgpd
, vtysh_exit_bgpd_cmd
, "exit",
2490 "Exit current mode and down to previous mode\n")
2492 return vtysh_exit(vty
);
2495 DEFUNSH(VTYSH_BGPD
, vtysh_quit_bgpd
, vtysh_quit_bgpd_cmd
, "quit",
2496 "Exit current mode and down to previous mode\n")
2498 return vtysh_exit_bgpd(self
, vty
, argc
, argv
);
2500 #endif /* HAVE_BGPD */
2503 DEFUNSH(VTYSH_OSPFD
, vtysh_exit_ospfd
, vtysh_exit_ospfd_cmd
, "exit",
2504 "Exit current mode and down to previous mode\n")
2506 return vtysh_exit(vty
);
2509 DEFUNSH(VTYSH_OSPFD
, vtysh_quit_ospfd
, vtysh_quit_ospfd_cmd
, "quit",
2510 "Exit current mode and down to previous mode\n")
2512 return vtysh_exit_ospfd(self
, vty
, argc
, argv
);
2514 #endif /* HAVE_OSPFD */
2517 DEFUNSH(VTYSH_EIGRPD
, vtysh_exit_eigrpd
, vtysh_exit_eigrpd_cmd
, "exit",
2518 "Exit current mode and down to previous mode\n")
2520 return vtysh_exit(vty
);
2523 DEFUNSH(VTYSH_EIGRPD
, vtysh_quit_eigrpd
, vtysh_quit_eigrpd_cmd
, "quit",
2524 "Exit current mode and down to previous mode\n")
2526 return vtysh_exit(vty
);
2528 #endif /* HAVE_EIGRPD */
2531 DEFUNSH(VTYSH_BABELD
, vtysh_exit_babeld
, vtysh_exit_babeld_cmd
, "exit",
2532 "Exit current mode and down to previous mode\n")
2534 return vtysh_exit(vty
);
2537 DEFUNSH(VTYSH_BABELD
, vtysh_quit_babeld
, vtysh_quit_babeld_cmd
, "quit",
2538 "Exit current mode and down to previous mode\n")
2540 return vtysh_exit(vty
);
2542 #endif /* HAVE_BABELD */
2545 DEFUNSH(VTYSH_OSPF6D
, vtysh_exit_ospf6d
, vtysh_exit_ospf6d_cmd
, "exit",
2546 "Exit current mode and down to previous mode\n")
2548 return vtysh_exit(vty
);
2551 DEFUNSH(VTYSH_OSPF6D
, vtysh_quit_ospf6d
, vtysh_quit_ospf6d_cmd
, "quit",
2552 "Exit current mode and down to previous mode\n")
2554 return vtysh_exit_ospf6d(self
, vty
, argc
, argv
);
2556 #endif /* HAVE_OSPF6D */
2558 #if defined(HAVE_LDPD)
2559 DEFUNSH(VTYSH_LDPD
, vtysh_exit_ldpd
, vtysh_exit_ldpd_cmd
, "exit",
2560 "Exit current mode and down to previous mode\n")
2562 return vtysh_exit(vty
);
2565 ALIAS(vtysh_exit_ldpd
, vtysh_quit_ldpd_cmd
, "quit",
2566 "Exit current mode and down to previous mode\n")
2570 DEFUNSH(VTYSH_ISISD
, vtysh_exit_isisd
, vtysh_exit_isisd_cmd
, "exit",
2571 "Exit current mode and down to previous mode\n")
2573 return vtysh_exit(vty
);
2576 DEFUNSH(VTYSH_ISISD
, vtysh_quit_isisd
, vtysh_quit_isisd_cmd
, "quit",
2577 "Exit current mode and down to previous mode\n")
2579 return vtysh_exit_isisd(self
, vty
, argc
, argv
);
2581 #endif /* HAVE_ISISD */
2584 DEFUNSH(VTYSH_BFDD
, vtysh_exit_bfdd
, vtysh_exit_bfdd_cmd
, "exit",
2585 "Exit current mode and down to previous mode\n")
2587 return vtysh_exit(vty
);
2590 ALIAS(vtysh_exit_bfdd
, vtysh_quit_bfdd_cmd
, "quit",
2591 "Exit current mode and down to previous mode\n")
2595 DEFUNSH(VTYSH_FABRICD
, vtysh_exit_fabricd
, vtysh_exit_fabricd_cmd
, "exit",
2596 "Exit current mode and down to previous mode\n")
2598 return vtysh_exit(vty
);
2601 DEFUNSH(VTYSH_FABRICD
, vtysh_quit_fabricd
, vtysh_quit_fabricd_cmd
, "quit",
2602 "Exit current mode and down to previous mode\n")
2604 return vtysh_exit_fabricd(self
, vty
, argc
, argv
);
2606 #endif /* HAVE_FABRICD */
2608 DEFUNSH(VTYSH_KEYS
, vtysh_exit_keys
, vtysh_exit_keys_cmd
, "exit",
2609 "Exit current mode and down to previous mode\n")
2611 return vtysh_exit(vty
);
2614 DEFUNSH(VTYSH_KEYS
, vtysh_quit_keys
, vtysh_quit_keys_cmd
, "quit",
2615 "Exit current mode and down to previous mode\n")
2617 return vtysh_exit_keys(self
, vty
, argc
, argv
);
2620 DEFUNSH(VTYSH_SR
, vtysh_exit_sr
, vtysh_exit_sr_cmd
, "exit",
2621 "Exit current mode and down to previous mode\n")
2623 return vtysh_exit(vty
);
2626 DEFUNSH(VTYSH_SR
, vtysh_quit_sr
, vtysh_quit_sr_cmd
, "quit",
2627 "Exit current mode and down to previous mode\n")
2629 return vtysh_exit(vty
);
2632 #if defined(HAVE_PATHD)
2633 DEFUNSH(VTYSH_PATHD
, vtysh_exit_pathd
, vtysh_exit_pathd_cmd
, "exit",
2634 "Exit current mode and down to previous mode\n")
2636 return vtysh_exit(vty
);
2639 DEFUNSH(VTYSH_PATHD
, vtysh_quit_pathd
, vtysh_quit_pathd_cmd
, "quit",
2640 "Exit current mode and down to previous mode\n")
2642 return vtysh_exit_pathd(self
, vty
, argc
, argv
);
2644 #endif /* HAVE_PATHD */
2646 DEFUNSH(VTYSH_ALL
, vtysh_exit_line_vty
, vtysh_exit_line_vty_cmd
, "exit",
2647 "Exit current mode and down to previous mode\n")
2649 return vtysh_exit(vty
);
2652 DEFUNSH(VTYSH_ALL
, vtysh_quit_line_vty
, vtysh_quit_line_vty_cmd
, "quit",
2653 "Exit current mode and down to previous mode\n")
2655 return vtysh_exit_line_vty(self
, vty
, argc
, argv
);
2658 DEFUNSH(VTYSH_INTERFACE
, vtysh_interface
, vtysh_interface_cmd
,
2659 "interface IFNAME [vrf NAME]",
2660 "Select an interface to configure\n"
2661 "Interface's name\n" VRF_CMD_HELP_STR
)
2663 vty
->node
= INTERFACE_NODE
;
2667 DEFUNSH(VTYSH_ZEBRA
, vtysh_pseudowire
, vtysh_pseudowire_cmd
,
2668 "pseudowire IFNAME",
2669 "Static pseudowire configuration\n"
2670 "Pseudowire name\n")
2672 vty
->node
= PW_NODE
;
2676 DEFUNSH(VTYSH_NH_GROUP
,
2677 vtysh_nexthop_group
, vtysh_nexthop_group_cmd
,
2678 "nexthop-group NHGNAME",
2679 "Nexthop Group configuration\n"
2680 "Name of the Nexthop Group\n")
2682 vty
->node
= NH_GROUP_NODE
;
2686 DEFSH(VTYSH_NH_GROUP
, vtysh_no_nexthop_group_cmd
,
2687 "no nexthop-group NHGNAME",
2689 "Nexthop Group Configuration\n"
2690 "Name of the Nexthop Group\n")
2692 DEFUNSH(VTYSH_VRF
, vtysh_vrf
, vtysh_vrf_cmd
, "vrf NAME",
2693 "Select a VRF to configure\n"
2696 vty
->node
= VRF_NODE
;
2700 DEFUNSH(VTYSH_VRF
, vtysh_exit_vrf
, vtysh_exit_vrf_cmd
, "exit",
2701 "Exit current mode and down to previous mode\n")
2703 return vtysh_exit(vty
);
2706 DEFUNSH(VTYSH_VRF
, vtysh_quit_vrf
, vtysh_quit_vrf_cmd
, "quit",
2707 "Exit current mode and down to previous mode\n")
2709 return vtysh_exit_vrf(self
, vty
, argc
, argv
);
2712 DEFUNSH(VTYSH_NH_GROUP
,
2713 vtysh_exit_nexthop_group
, vtysh_exit_nexthop_group_cmd
,
2714 "exit", "Exit current mode and down to previous mode\n")
2716 return vtysh_exit(vty
);
2719 DEFUNSH(VTYSH_NH_GROUP
,
2720 vtysh_quit_nexthop_group
, vtysh_quit_nexthop_group_cmd
,
2721 "quit", "Exit current mode and down to previous mode\n")
2723 return vtysh_exit_nexthop_group(self
, vty
, argc
, argv
);
2726 DEFUNSH(VTYSH_INTERFACE
, vtysh_exit_interface
, vtysh_exit_interface_cmd
, "exit",
2727 "Exit current mode and down to previous mode\n")
2729 return vtysh_exit(vty
);
2732 DEFUNSH(VTYSH_INTERFACE
, vtysh_quit_interface
, vtysh_quit_interface_cmd
, "quit",
2733 "Exit current mode and down to previous mode\n")
2735 return vtysh_exit_interface(self
, vty
, argc
, argv
);
2738 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_pseudowire
, vtysh_exit_pseudowire_cmd
, "exit",
2739 "Exit current mode and down to previous mode\n")
2741 return vtysh_exit(vty
);
2744 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_pseudowire
, vtysh_quit_pseudowire_cmd
, "quit",
2745 "Exit current mode and down to previous mode\n")
2747 return vtysh_exit_pseudowire(self
, vty
, argc
, argv
);
2750 static char *do_prepend(struct vty
*vty
, struct cmd_token
**argv
, int argc
)
2752 const char *argstr
[argc
+ 1];
2755 if (vty
->node
!= VIEW_NODE
) {
2760 for (i
= 0; i
< argc
; i
++)
2761 argstr
[i
+ off
] = argv
[i
]->arg
;
2763 return frrstr_join(argstr
, argc
+ off
, " ");
2766 #pragma GCC diagnostic push
2767 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2768 /* 'headline' is a format string with a %s for the daemon name
2770 * Also for some reason GCC emits the warning on the end of the function
2771 * (optimization maybe?) rather than on the vty_out line, so this pragma
2772 * wraps the entire function rather than just the vty_out line.
2775 static int show_per_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2776 const char *headline
)
2779 int ret
= CMD_SUCCESS
;
2780 char *line
= do_prepend(vty
, argv
, argc
);
2782 for (i
= 0; i
< array_size(vtysh_client
); i
++)
2783 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
2784 vty_out(vty
, headline
, vtysh_client
[i
].name
);
2785 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
2789 XFREE(MTYPE_TMP
, line
);
2793 #pragma GCC diagnostic pop
2795 static int show_one_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2799 char *line
= do_prepend(vty
, argv
, argc
);
2801 ret
= vtysh_client_execute_name(name
, line
);
2803 XFREE(MTYPE_TMP
, line
);
2808 DEFUN (vtysh_show_thread_timer
,
2809 vtysh_show_thread_timer_cmd
,
2810 "show thread timers",
2812 "Thread information\n"
2813 "Show all timers and how long they have in the system\n")
2815 return show_per_daemon(vty
, argv
, argc
, "Thread timers for %s:\n");
2818 DEFUN (vtysh_show_poll
,
2819 vtysh_show_poll_cmd
,
2822 "Thread information\n"
2823 "Thread Poll Information\n")
2825 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2828 DEFUN (vtysh_show_thread
,
2829 vtysh_show_thread_cmd
,
2830 "show thread cpu [FILTER]",
2832 "Thread information\n"
2833 "Thread CPU usage\n"
2834 "Display filter (rwtexb)\n")
2836 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2839 DEFUN (vtysh_show_work_queues
,
2840 vtysh_show_work_queues_cmd
,
2843 "Work Queue information\n")
2845 return show_per_daemon(vty
, argv
, argc
,
2846 "Work queue statistics for %s:\n");
2849 DEFUN (vtysh_show_work_queues_daemon
,
2850 vtysh_show_work_queues_daemon_cmd
,
2851 "show work-queues " DAEMONS_LIST
,
2853 "Work Queue information\n"
2856 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2859 DEFUNSH(VTYSH_ZEBRA
, vtysh_link_params
, vtysh_link_params_cmd
, "link-params",
2862 vty
->node
= LINK_PARAMS_NODE
;
2866 DEFUNSH(VTYSH_ZEBRA
, exit_link_params
, exit_link_params_cmd
, "exit-link-params",
2867 "Exit from Link Params configuration node\n")
2869 if (vty
->node
== LINK_PARAMS_NODE
)
2870 vty
->node
= INTERFACE_NODE
;
2874 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_link_params
, vtysh_exit_link_params_cmd
, "exit",
2875 "Exit current mode and down to previous mode\n")
2877 if (vty
->node
== LINK_PARAMS_NODE
)
2878 vty
->node
= INTERFACE_NODE
;
2882 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_link_params
, vtysh_quit_link_params_cmd
, "quit",
2883 "Exit current mode and down to previous mode\n")
2885 return vtysh_exit_link_params(self
, vty
, argc
, argv
);
2888 DEFUNSH_HIDDEN (0x00,
2890 vtysh_debug_all_cmd
,
2894 "Toggle all debugs on or off\n")
2899 DEFUN (vtysh_show_debugging
,
2900 vtysh_show_debugging_cmd
,
2905 return show_per_daemon(vty
, argv
, argc
, "");
2908 DEFUN (vtysh_show_debugging_hashtable
,
2909 vtysh_show_debugging_hashtable_cmd
,
2910 "show debugging hashtable [statistics]",
2913 "Statistics about hash tables\n"
2914 "Statistics about hash tables\n")
2916 bool stats
= strmatch(argv
[argc
- 1]->text
, "statistics");
2920 "Load factor (LF) - average number of elements across all buckets\n");
2922 "Full load factor (FLF) - average number of elements across full buckets\n\n");
2924 "Standard deviation (SD) is calculated for both the LF and FLF\n");
2926 "and indicates the typical deviation of bucket chain length\n");
2927 vty_out(vty
, "from the value in the corresponding load factor.\n\n");
2929 return show_per_daemon(vty
, argv
, stats
? argc
- 1 : argc
,
2930 "Hashtable statistics for %s:\n");
2933 DEFUN (vtysh_show_error_code
,
2934 vtysh_show_error_code_cmd
,
2935 "show error <(1-4294967296)|all> [json]",
2937 "Information on errors\n"
2938 "Error code to get info about\n"
2939 "Information on all errors\n"
2944 if (!strmatch(argv
[2]->text
, "all"))
2945 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2947 /* If it's not a shared code, send it to all the daemons */
2948 if (arg
< LIB_FERR_START
|| arg
> LIB_FERR_END
) {
2949 show_per_daemon(vty
, argv
, argc
, "");
2950 /* Otherwise, print it ourselves to avoid duplication */
2952 bool json
= strmatch(argv
[argc
- 1]->text
, "json");
2954 if (!strmatch(argv
[2]->text
, "all"))
2955 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2957 log_ref_display(vty
, arg
, json
);
2964 DEFUN_HIDDEN (show_config_running
,
2965 show_config_running_cmd
,
2966 "show configuration running\
2967 [<json|xml> [translate WORD]]\
2968 [with-defaults] " DAEMONS_LIST
,
2970 "Configuration information\n"
2971 "Running configuration\n"
2972 "Change output format to JSON\n"
2973 "Change output format to XML\n"
2974 "Translate output\n"
2975 "YANG module translator\n"
2976 "Show default values\n"
2979 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2982 DEFUN (show_yang_operational_data
,
2983 show_yang_operational_data_cmd
,
2984 "show yang operational-data XPATH\
2991 "YANG information\n"
2992 "Show YANG operational data\n"
2993 "XPath expression specifying the YANG data path\n"
2994 "Set the output format\n"
2995 "JavaScript Object Notation\n"
2996 "Extensible Markup Language\n"
2997 "Translate operational data\n"
2998 "YANG module translator\n"
2999 "Merge configuration data\n"
3002 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3005 DEFUN(show_yang_module
, show_yang_module_cmd
,
3006 "show yang module [module-translator WORD] " DAEMONS_LIST
,
3008 "YANG information\n"
3009 "Show loaded modules\n"
3010 "YANG module translator\n"
3011 "YANG module translator\n" DAEMONS_STR
)
3013 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3016 DEFUN(show_yang_module_detail
, show_yang_module_detail_cmd
,
3018 [module-translator WORD]\
3019 WORD <compiled|summary|tree|yang|yin> " DAEMONS_LIST
,
3021 "YANG information\n"
3022 "Show loaded modules\n"
3023 "YANG module translator\n"
3024 "YANG module translator\n"
3026 "Display compiled module in YANG format\n"
3027 "Display summary information about the module\n"
3028 "Display module in the tree (RFC 8340) format\n"
3029 "Display module in the YANG format\n"
3030 "Display module in the YIN format\n" DAEMONS_STR
)
3032 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3036 DEFUNSH(VTYSH_ALL
, debug_nb
,
3038 "[no] debug northbound\
3040 callbacks [{configuration|state|rpc}]\
3047 "Northbound debugging\n"
3054 "libyang debugging\n")
3059 DEFUN (vtysh_show_history
,
3060 vtysh_show_history_cmd
,
3063 "The list of commands stored in history\n")
3065 HIST_ENTRY
**hlist
= history_list();
3069 vty_out(vty
, "%s\n", hlist
[i
]->line
);
3076 DEFUN (vtysh_show_memory
,
3077 vtysh_show_memory_cmd
,
3078 "show memory [" DAEMONS_LIST
"]",
3080 "Memory statistics\n"
3084 return show_one_daemon(vty
, argv
, argc
- 1,
3085 argv
[argc
- 1]->text
);
3087 return show_per_daemon(vty
, argv
, argc
, "Memory statistics for %s:\n");
3090 DEFUN (vtysh_show_modules
,
3091 vtysh_show_modules_cmd
,
3096 return show_per_daemon(vty
, argv
, argc
, "Module information for %s:\n");
3099 /* Logging commands. */
3100 DEFUN (vtysh_show_logging
,
3101 vtysh_show_logging_cmd
,
3104 "Show current logging configuration\n")
3106 return show_per_daemon(vty
, argv
, argc
,
3107 "Logging configuration for %s:\n");
3110 DEFUNSH(VTYSH_ALL
, vtysh_debug_memstats
,
3111 vtysh_debug_memstats_cmd
, "[no] debug memstats-at-exit",
3114 "Print memory statistics at exit\n")
3119 DEFUN(vtysh_debug_uid_backtrace
,
3120 vtysh_debug_uid_backtrace_cmd
,
3121 "[no] debug unique-id UID backtrace",
3124 "Options per individual log message, by unique ID\n"
3125 "Log message unique ID (XXXXX-XXXXX)\n"
3126 "Add backtrace to log when message is printed\n")
3128 unsigned int i
, ok
= 0;
3129 int err
= CMD_SUCCESS
, ret
;
3133 if (!strcmp(argv
[0]->text
, "no")) {
3135 snprintfrr(line
, sizeof(line
),
3136 "no debug unique-id %s backtrace", uid
);
3139 snprintfrr(line
, sizeof(line
), "debug unique-id %s backtrace",
3143 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3144 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
3145 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3150 case CMD_ERR_NOTHING_TODO
:
3151 /* ignore this daemon
3153 * note this doesn't need to handle instances
3154 * of the same daemon individually because
3155 * the same daemon will have the same UIDs
3159 if (err
== CMD_SUCCESS
)
3165 if (err
== CMD_SUCCESS
&& !ok
) {
3166 vty_out(vty
, "%% no running daemon recognizes unique-ID %s\n",
3173 DEFUNSH(VTYSH_ALL
, vtysh_allow_reserved_ranges
, vtysh_allow_reserved_ranges_cmd
,
3174 "allow-reserved-ranges",
3175 "Allow using IPv4 (Class E) reserved IP space\n")
3180 DEFUNSH(VTYSH_ALL
, no_vtysh_allow_reserved_ranges
,
3181 no_vtysh_allow_reserved_ranges_cmd
, "no allow-reserved-ranges",
3182 NO_STR
"Allow using IPv4 (Class E) reserved IP space\n")
3187 DEFUNSH(VTYSH_ALL
, vtysh_service_password_encrypt
,
3188 vtysh_service_password_encrypt_cmd
, "service password-encryption",
3189 "Set up miscellaneous service\n"
3190 "Enable encrypted passwords\n")
3195 DEFUNSH(VTYSH_ALL
, no_vtysh_service_password_encrypt
,
3196 no_vtysh_service_password_encrypt_cmd
, "no service password-encryption",
3198 "Set up miscellaneous service\n"
3199 "Enable encrypted passwords\n")
3204 DEFUNSH(VTYSH_ALL
, vtysh_config_password
, vtysh_password_cmd
,
3205 "password [(8-8)] LINE",
3206 "Modify the terminal connection password\n"
3207 "Specifies a HIDDEN password will follow\n"
3208 "The password string\n")
3213 DEFUNSH(VTYSH_ALL
, no_vtysh_config_password
, no_vtysh_password_cmd
,
3214 "no password", NO_STR
3215 "Modify the terminal connection password\n")
3217 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3222 DEFUNSH(VTYSH_ALL
, vtysh_config_enable_password
, vtysh_enable_password_cmd
,
3223 "enable password [(8-8)] LINE",
3224 "Modify enable password parameters\n"
3225 "Assign the privileged level password\n"
3226 "Specifies a HIDDEN password will follow\n"
3227 "The 'enable' password string\n")
3232 DEFUNSH(VTYSH_ALL
, no_vtysh_config_enable_password
,
3233 no_vtysh_enable_password_cmd
, "no enable password", NO_STR
3234 "Modify enable password parameters\n"
3235 "Assign the privileged level password\n")
3237 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3242 DEFUN (vtysh_write_terminal
,
3243 vtysh_write_terminal_cmd
,
3244 "write terminal ["DAEMONS_LIST
"] [no-header]",
3245 "Write running configuration to memory, network, or terminal\n"
3246 "Write to terminal\n"
3248 "Skip \"Building configuration...\" header\n")
3251 char line
[] = "do write terminal";
3253 if (!strcmp(argv
[argc
- 1]->arg
, "no-header"))
3256 vty_out(vty
, "Building configuration...\n");
3257 vty_out(vty
, "\nCurrent configuration:\n");
3258 vty_out(vty
, "!\n");
3261 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3263 || (strmatch(vtysh_client
[i
].name
, argv
[2]->text
)))
3264 vtysh_client_config(&vtysh_client
[i
], line
);
3266 /* Integrate vtysh specific configuration. */
3267 vty_open_pager(vty
);
3268 vtysh_config_write();
3269 vtysh_config_dump();
3270 vty_close_pager(vty
);
3271 vty_out(vty
, "end\n");
3276 DEFUN (vtysh_show_running_config
,
3277 vtysh_show_running_config_cmd
,
3278 "show running-config ["DAEMONS_LIST
"] [no-header]",
3280 "Current operating configuration\n"
3282 "Skip \"Building configuration...\" header\n")
3284 return vtysh_write_terminal(self
, vty
, argc
, argv
);
3287 DEFUN (vtysh_integrated_config
,
3288 vtysh_integrated_config_cmd
,
3289 "service integrated-vtysh-config",
3290 "Set up miscellaneous service\n"
3291 "Write configuration into integrated file\n")
3293 vtysh_write_integrated
= WRITE_INTEGRATED_YES
;
3297 DEFUN (no_vtysh_integrated_config
,
3298 no_vtysh_integrated_config_cmd
,
3299 "no service integrated-vtysh-config",
3301 "Set up miscellaneous service\n"
3302 "Write configuration into integrated file\n")
3304 vtysh_write_integrated
= WRITE_INTEGRATED_NO
;
3308 static void backup_config_file(const char *fbackup
)
3310 char *integrate_sav
= NULL
;
3312 size_t integrate_sav_sz
= strlen(fbackup
) + strlen(CONF_BACKUP_EXT
) + 1;
3313 integrate_sav
= malloc(integrate_sav_sz
);
3314 strlcpy(integrate_sav
, fbackup
, integrate_sav_sz
);
3315 strlcat(integrate_sav
, CONF_BACKUP_EXT
, integrate_sav_sz
);
3317 /* Move current configuration file to backup config file. */
3318 if (unlink(integrate_sav
) != 0 && errno
!= ENOENT
)
3319 vty_out(vty
, "Unlink failed for %s: %s\n", integrate_sav
,
3321 if (rename(fbackup
, integrate_sav
) != 0 && errno
!= ENOENT
)
3322 vty_out(vty
, "Error renaming %s to %s: %s\n", fbackup
,
3323 integrate_sav
, strerror(errno
));
3324 free(integrate_sav
);
3327 int vtysh_write_config_integrated(void)
3330 char line
[] = "do write terminal";
3334 struct passwd
*pwentry
;
3337 struct group
*grentry
;
3344 vty_out(vty
, "Building Configuration...\n");
3346 backup_config_file(frr_config
);
3347 fp
= fopen(frr_config
, "w");
3350 "%% Error: failed to open configuration file %s: %s\n",
3351 frr_config
, safe_strerror(errno
));
3352 return CMD_WARNING_CONFIG_FAILED
;
3356 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3357 vtysh_client_config(&vtysh_client
[i
], line
);
3359 vtysh_config_write();
3360 vty
->of_saved
= vty
->of
;
3362 vtysh_config_dump();
3363 vty
->of
= vty
->of_saved
;
3365 if (fchmod(fd
, CONFIGFILE_MASK
) != 0) {
3366 printf("%% Warning: can't chmod configuration file %s: %s\n",
3367 frr_config
, safe_strerror(errno
));
3372 pwentry
= getpwnam(FRR_USER
);
3374 uid
= pwentry
->pw_uid
;
3376 printf("%% Warning: could not look up user \"%s\"\n", FRR_USER
);
3381 grentry
= getgrnam(FRR_GROUP
);
3383 gid
= grentry
->gr_gid
;
3385 printf("%% Warning: could not look up group \"%s\"\n",
3391 if (!fstat(fd
, &st
)) {
3392 if (st
.st_uid
== uid
)
3394 if (st
.st_gid
== gid
)
3396 if ((uid
!= (uid_t
)-1 || gid
!= (gid_t
)-1)
3397 && fchown(fd
, uid
, gid
)) {
3398 printf("%% Warning: can't chown configuration file %s: %s\n",
3399 frr_config
, safe_strerror(errno
));
3403 printf("%% Warning: stat() failed on %s: %s\n", frr_config
,
3404 safe_strerror(errno
));
3408 if (fflush(fp
) != 0) {
3409 printf("%% Warning: fflush() failed on %s: %s\n", frr_config
,
3410 safe_strerror(errno
));
3414 if (fsync(fd
) < 0) {
3415 printf("%% Warning: fsync() failed on %s: %s\n", frr_config
,
3416 safe_strerror(errno
));
3422 printf("Integrated configuration saved to %s\n", frr_config
);
3430 DEFUN_HIDDEN(start_config
, start_config_cmd
, "XFRR_start_configuration",
3431 "The Beginning of Configuration\n")
3434 char line
[] = "XFRR_start_configuration";
3436 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3437 vtysh_client_execute(&vtysh_client
[i
], line
);
3442 DEFUN_HIDDEN(end_config
, end_config_cmd
, "XFRR_end_configuration",
3443 "The End of Configuration\n")
3446 char line
[] = "XFRR_end_configuration";
3448 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3449 vtysh_client_execute(&vtysh_client
[i
], line
);
3454 static bool want_config_integrated(void)
3458 switch (vtysh_write_integrated
) {
3459 case WRITE_INTEGRATED_UNSPECIFIED
:
3460 if (stat(frr_config
, &s
) && errno
== ENOENT
)
3463 case WRITE_INTEGRATED_NO
:
3465 case WRITE_INTEGRATED_YES
:
3471 DEFUN (vtysh_write_memory
,
3472 vtysh_write_memory_cmd
,
3473 "write [<memory|file>]",
3474 "Write running configuration to memory, network, or terminal\n"
3475 "Write configuration to the file (same as write file)\n"
3476 "Write configuration to the file (same as write memory)\n")
3478 int ret
= CMD_SUCCESS
;
3479 char line
[] = "do write memory";
3482 vty_out(vty
, "Note: this version of vtysh never writes vtysh.conf\n");
3484 /* If integrated frr.conf explicitly set. */
3485 if (want_config_integrated()) {
3486 ret
= CMD_WARNING_CONFIG_FAILED
;
3488 /* first attempt to use watchfrr if it's available */
3489 bool used_watchfrr
= false;
3491 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3492 if (vtysh_client
[i
].flag
== VTYSH_WATCHFRR
)
3494 if (i
< array_size(vtysh_client
) && vtysh_client
[i
].fd
!= -1) {
3495 used_watchfrr
= true;
3496 ret
= vtysh_client_execute(&vtysh_client
[i
],
3497 "do write integrated");
3501 * If we didn't use watchfrr, fallback to writing the config
3504 if (!used_watchfrr
) {
3505 printf("\nWarning: attempting direct configuration write without watchfrr.\nFile permissions and ownership may be incorrect, or write may fail.\n\n");
3506 ret
= vtysh_write_config_integrated();
3511 vty_out(vty
, "Building Configuration...\n");
3513 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3514 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3519 DEFUN (vtysh_copy_running_config
,
3520 vtysh_copy_running_config_cmd
,
3521 "copy running-config startup-config",
3522 "Copy from one file to another\n"
3523 "Copy from current system configuration\n"
3524 "Copy to startup configuration\n")
3526 return vtysh_write_memory(self
, vty
, argc
, argv
);
3529 DEFUN (vtysh_copy_to_running
,
3530 vtysh_copy_to_running_cmd
,
3531 "copy FILENAME running-config",
3532 "Apply a configuration file\n"
3533 "Configuration file to read\n"
3534 "Apply to current configuration\n")
3537 const char *fname
= argv
[1]->arg
;
3539 ret
= vtysh_apply_config(fname
, true, false);
3541 /* Return to enable mode - the 'read_config' api leaves us up a level */
3542 vtysh_execute_no_pager("enable");
3547 DEFUN (vtysh_terminal_paginate
,
3548 vtysh_terminal_paginate_cmd
,
3549 "[no] terminal paginate",
3551 "Set terminal line parameters\n"
3552 "Use pager for output scrolling\n")
3554 free(vtysh_pager_name
);
3555 vtysh_pager_name
= NULL
;
3557 if (strcmp(argv
[0]->text
, "no"))
3558 vtysh_pager_envdef(true);
3562 DEFUN (vtysh_terminal_length
,
3563 vtysh_terminal_length_cmd
,
3564 "[no] terminal length (0-4294967295)",
3566 "Set terminal line parameters\n"
3567 "Set number of lines on a screen\n"
3568 "Number of lines on screen (0 for no pausing, nonzero to use pager)\n")
3571 unsigned long lines
;
3573 free(vtysh_pager_name
);
3574 vtysh_pager_name
= NULL
;
3576 if (!strcmp(argv
[0]->text
, "no") || !strcmp(argv
[1]->text
, "no")) {
3577 /* "terminal no length" = use VTYSH_PAGER */
3578 vtysh_pager_envdef(true);
3582 lines
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
3585 "%% The \"terminal length\" command is deprecated and its value is ignored.\n"
3586 "%% Please use \"terminal paginate\" instead with OS TTY length handling.\n");
3587 vtysh_pager_envdef(true);
3593 ALIAS_DEPRECATED(vtysh_terminal_length
,
3594 vtysh_terminal_no_length_cmd
,
3595 "terminal no length",
3596 "Set terminal line parameters\n"
3598 "Set number of lines on a screen\n")
3600 DEFUN (vtysh_show_daemons
,
3601 vtysh_show_daemons_cmd
,
3604 "Show list of running daemons\n")
3608 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3609 if (vtysh_client
[i
].fd
>= 0)
3610 vty_out(vty
, " %s", vtysh_client
[i
].name
);
3616 struct visual_prio
{
3617 /* 4 characters for nice alignment */
3620 int c256_background
;
3624 /* clang-format off */
3625 struct visual_prio visual_prios
[] = {
3627 .label
= "\e[31;1mEMRG",
3628 .c256_background
= 53,
3629 .c256_formatarg
= 225,
3632 .label
= "\e[31;1mALRT",
3633 .c256_background
= 53,
3634 .c256_formatarg
= 225,
3637 .label
= "\e[31;1mCRIT",
3638 .c256_background
= 53,
3639 .c256_formatarg
= 225,
3642 .label
= "\e[38;5;202mERR!",
3643 .c256_background
= 52,
3644 .c256_formatarg
= 224,
3647 .label
= "\e[38;5;222mWARN",
3648 .c256_background
= 58,
3649 .c256_formatarg
= 230,
3653 .c256_background
= 234,
3654 .c256_formatarg
= 195,
3657 .label
= "\e[38;5;192mINFO",
3658 .c256_background
= 236,
3659 .c256_formatarg
= 195,
3662 .label
= "\e[38;5;116mDEBG",
3663 .c256_background
= 238,
3664 .c256_formatarg
= 195,
3667 /* clang-format on */
3669 static void vtysh_log_print(struct vtysh_client
*vclient
,
3670 struct zlog_live_hdr
*hdr
, const char *text
)
3672 size_t textlen
= hdr
->textlen
, textpos
= 0;
3673 time_t ts
= hdr
->ts_sec
;
3674 struct visual_prio
*vis
;
3678 if (hdr
->prio
>= array_size(visual_prios
))
3679 vis
= &visual_prios
[LOG_CRIT
];
3681 vis
= &visual_prios
[hdr
->prio
];
3683 localtime_r(&ts
, &tm
);
3684 strftime(ts_buf
, sizeof(ts_buf
), "%Y-%m-%d %H:%M:%S", &tm
);
3687 const char *label
= vis
->label
+ strlen(vis
->label
) - 4;
3689 fprintf(stderr
, "%s.%03u [%s] %s: %.*s\n", ts_buf
,
3690 hdr
->ts_nsec
/ 1000000U, label
, vclient
->name
,
3691 (int)textlen
, text
);
3696 "\e[48;5;%dm\e[38;5;247m%s.%03u [%s\e[38;5;247m] \e[38;5;255m%s\e[38;5;247m: \e[38;5;251m",
3697 vis
->c256_background
, ts_buf
, hdr
->ts_nsec
/ 1000000U,
3698 vis
->label
, vclient
->name
);
3700 for (size_t fmtpos
= 0; fmtpos
< hdr
->n_argpos
; fmtpos
++) {
3701 struct fmt_outpos
*fmt
= &hdr
->argpos
[fmtpos
];
3703 if (fmt
->off_start
< textpos
|| fmt
->off_end
< fmt
->off_start
||
3704 fmt
->off_end
> textlen
)
3707 while (fmt
->off_end
> fmt
->off_start
&&
3708 text
[fmt
->off_end
- 1] == ' ')
3711 fprintf(stderr
, "%.*s\e[38;5;%dm%.*s\e[38;5;251m",
3712 (int)(fmt
->off_start
- textpos
), text
+ textpos
,
3713 vis
->c256_formatarg
,
3714 (int)(fmt
->off_end
- fmt
->off_start
),
3715 text
+ fmt
->off_start
);
3716 textpos
= fmt
->off_end
;
3718 fprintf(stderr
, "%.*s\033[K\033[m\n", (int)(textlen
- textpos
),
3722 static void vtysh_log_read(struct event
*thread
)
3724 struct vtysh_client
*vclient
= EVENT_ARG(thread
);
3726 struct zlog_live_hdr hdr
;
3732 event_add_read(master
, vtysh_log_read
, vclient
, vclient
->log_fd
,
3733 &vclient
->log_reader
);
3735 ret
= recv(vclient
->log_fd
, &buf
, sizeof(buf
), 0);
3737 if (ret
< 0 && ERRNO_IO_RETRY(errno
))
3740 if (stderr_stdout_same
) {
3741 #ifdef HAVE_RL_CLEAR_VISIBLE_LINE
3742 rl_clear_visible_line();
3752 buf
.text
[0] = '\0'; /* coverity */
3755 snprintfrr(buf
.text
, sizeof(buf
.text
),
3756 "log monitor connection error: %m");
3759 buf
.text
, sizeof(buf
.text
),
3760 "log monitor connection closed unexpectedly");
3761 buf
.hdr
.textlen
= strlen(buf
.text
);
3763 EVENT_OFF(vclient
->log_reader
);
3764 close(vclient
->log_fd
);
3765 vclient
->log_fd
= -1;
3767 clock_gettime(CLOCK_REALTIME
, &ts
);
3768 buf
.hdr
.ts_sec
= ts
.tv_sec
;
3769 buf
.hdr
.ts_nsec
= ts
.tv_nsec
;
3770 buf
.hdr
.prio
= LOG_ERR
;
3772 buf
.hdr
.texthdrlen
= 0;
3773 buf
.hdr
.n_argpos
= 0;
3775 int32_t lost_msgs
= buf
.hdr
.lost_msgs
- vclient
->lost_msgs
;
3777 if (lost_msgs
> 0) {
3778 vclient
->lost_msgs
= buf
.hdr
.lost_msgs
;
3780 "%d log messages from %s lost (vtysh reading too slowly)\n",
3781 lost_msgs
, vclient
->name
);
3785 text
= buf
.text
+ sizeof(buf
.hdr
.argpos
[0]) * buf
.hdr
.n_argpos
;
3786 vtysh_log_print(vclient
, &buf
.hdr
, text
);
3788 if (stderr_stdout_same
)
3789 rl_forced_update_display();
3795 /* clippy/clidef can't process the DEFPY below without some value for this */
3796 #define DAEMONS_LIST "daemon"
3799 DEFPY (vtysh_terminal_monitor
,
3800 vtysh_terminal_monitor_cmd
,
3801 "terminal monitor ["DAEMONS_LIST
"]$daemon",
3802 "Set terminal line parameters\n"
3803 "Receive log messages to active VTY session\n"
3806 static const char line
[] = "terminal monitor";
3807 int ret_all
= CMD_SUCCESS
, ret
, fd
;
3810 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3811 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3813 if (daemon
&& strcmp(vclient
->name
, daemon
))
3816 for (; vclient
; vclient
= vclient
->next
) {
3817 if (vclient
->log_fd
!= -1) {
3818 vty_out(vty
, "%% %s: already monitoring logs\n",
3825 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, &fd
);
3827 set_nonblocking(fd
);
3828 vclient
->log_fd
= fd
;
3829 event_add_read(master
, vtysh_log_read
, vclient
,
3831 &vclient
->log_reader
);
3833 if (ret
!= CMD_SUCCESS
) {
3834 vty_out(vty
, "%% failed to enable logs on %s\n",
3836 ret_all
= CMD_WARNING
;
3842 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3844 "%% command had no effect, relevant daemons not connected?\n");
3845 ret_all
= CMD_WARNING
;
3850 DEFPY (no_vtysh_terminal_monitor
,
3851 no_vtysh_terminal_monitor_cmd
,
3852 "no terminal monitor ["DAEMONS_LIST
"]$daemon",
3854 "Set terminal line parameters\n"
3855 "Receive log messages to active VTY session\n"
3858 static const char line
[] = "no terminal monitor";
3859 int ret_all
= CMD_SUCCESS
, ret
;
3862 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3863 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3865 if (daemon
&& strcmp(vclient
->name
, daemon
))
3868 for (; vclient
; vclient
= vclient
->next
) {
3869 /* run this even if log_fd == -1, in case something
3872 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, NULL
);
3873 if (ret
!= CMD_SUCCESS
) {
3875 "%% failed to disable logs on %s\n",
3877 ret_all
= CMD_WARNING
;
3881 /* with this being a datagram socket, we can't expect
3882 * a close notification...
3884 if (vclient
->log_fd
!= -1) {
3885 EVENT_OFF(vclient
->log_reader
);
3887 close(vclient
->log_fd
);
3888 vclient
->log_fd
= -1;
3893 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3895 "%% command had no effect, relevant daemons not connected?\n");
3896 ret_all
= CMD_WARNING
;
3902 /* Execute command in child process. */
3903 static void execute_command(const char *command
, int argc
, const char *arg1
,
3913 /* Failure of fork(). */
3914 fprintf(stderr
, "Can't fork: %s\n", safe_strerror(errno
));
3916 } else if (pid
== 0) {
3917 /* This is child process. */
3920 execlp(command
, command
, (const char *)NULL
);
3923 execlp(command
, command
, arg1
, (const char *)NULL
);
3926 execlp(command
, command
, arg1
, arg2
,
3927 (const char *)NULL
);
3931 /* When execlp suceed, this part is not executed. */
3932 fprintf(stderr
, "Can't execute %s: %s\n", command
,
3933 safe_strerror(errno
));
3936 /* This is parent. */
3938 wait4(pid
, &status
, 0, NULL
);
3946 "Send echo messages\n"
3947 "Ping destination address or hostname\n")
3951 argv_find(argv
, argc
, "WORD", &idx
);
3952 execute_command("ping", 1, argv
[idx
]->arg
, NULL
);
3956 DEFUN(vtysh_motd
, vtysh_motd_cmd
, "show motd", SHOW_STR
"Show motd\n")
3962 ALIAS(vtysh_ping
, vtysh_ping_ip_cmd
, "ping ip WORD",
3963 "Send echo messages\n"
3965 "Ping destination address or hostname\n")
3967 DEFUN (vtysh_traceroute
,
3968 vtysh_traceroute_cmd
,
3970 "Trace route to destination\n"
3971 "Trace route to destination address or hostname\n")
3975 argv_find(argv
, argc
, "WORD", &idx
);
3976 execute_command("traceroute", 1, argv
[idx
]->arg
, NULL
);
3980 ALIAS(vtysh_traceroute
, vtysh_traceroute_ip_cmd
, "traceroute ip WORD",
3981 "Trace route to destination\n"
3983 "Trace route to destination address or hostname\n")
3985 DEFUN (vtysh_mtrace
,
3987 "mtrace WORD [WORD]",
3988 "Multicast trace route to multicast source\n"
3989 "Multicast trace route to multicast source address\n"
3990 "Multicast trace route for multicast group address\n")
3993 execute_command("mtracebis", 1, argv
[1]->arg
, NULL
);
3995 execute_command("mtracebis", 2, argv
[1]->arg
, argv
[2]->arg
);
4002 "Send echo messages\n"
4004 "Ping destination address or hostname\n")
4006 execute_command("ping6", 1, argv
[2]->arg
, NULL
);
4010 DEFUN (vtysh_traceroute6
,
4011 vtysh_traceroute6_cmd
,
4012 "traceroute ipv6 WORD",
4013 "Trace route to destination\n"
4015 "Trace route to destination address or hostname\n")
4017 execute_command("traceroute6", 1, argv
[2]->arg
, NULL
);
4021 #if CONFDATE > 20240201
4022 CPP_NOTICE("Remove HAVE_SHELL_ACCESS and it's documentation");
4024 #if defined(HAVE_SHELL_ACCESS)
4025 DEFUN (vtysh_telnet
,
4028 "Open a telnet connection\n"
4029 "IP address or hostname of a remote system\n")
4031 execute_command("telnet", 1, argv
[1]->arg
, NULL
);
4035 DEFUN (vtysh_telnet_port
,
4036 vtysh_telnet_port_cmd
,
4038 "Open a telnet connection\n"
4039 "IP address or hostname of a remote system\n"
4040 "TCP Port number\n")
4042 execute_command("telnet", 2, argv
[1]->arg
, argv
[2]->arg
);
4049 "Open an ssh connection\n"
4052 execute_command("ssh", 1, argv
[1]->arg
, NULL
);
4056 DEFUN (vtysh_start_shell
,
4057 vtysh_start_shell_cmd
,
4059 "Start UNIX shell\n")
4061 execute_command("sh", 0, NULL
, NULL
);
4065 DEFUN (vtysh_start_bash
,
4066 vtysh_start_bash_cmd
,
4068 "Start UNIX shell\n"
4071 execute_command("bash", 0, NULL
, NULL
);
4075 DEFUN (vtysh_start_zsh
,
4076 vtysh_start_zsh_cmd
,
4078 "Start UNIX shell\n"
4081 execute_command("zsh", 0, NULL
, NULL
);
4088 "list [permutations]",
4089 "Print command list\n"
4090 "Print all possible command permutations\n")
4092 return cmd_list_cmds(vty
, argc
== 2);
4095 DEFUN (vtysh_output_file
,
4096 vtysh_output_file_cmd
,
4098 "Direct vtysh output to file\n"
4099 "Direct vtysh output to file\n"
4100 "Path to dump output to\n")
4102 const char *path
= argv
[argc
- 1]->arg
;
4103 vty
->of
= fopen(path
, "a");
4105 vty_out(vty
, "Failed to open file '%s': %s\n", path
,
4106 safe_strerror(errno
));
4112 DEFUN (no_vtysh_output_file
,
4113 no_vtysh_output_file_cmd
,
4114 "no output file [FILE]",
4116 "Direct vtysh output to file\n"
4117 "Direct vtysh output to file\n"
4118 "Path to dump output to\n")
4120 if (vty
->of
!= stdout
) {
4130 "Find CLI command matching a regular expression\n"
4131 "Search pattern (POSIX regex)\n")
4133 return cmd_find_cmds(vty
, argv
, argc
);
4136 DEFUN_HIDDEN(show_cli_graph_vtysh
,
4137 show_cli_graph_vtysh_cmd
,
4141 "Dump current command space as DOT graph\n")
4143 struct cmd_node
*cn
= vector_slot(cmdvec
, vty
->node
);
4144 char *dot
= cmd_graph_dump_dot(cn
->cmdgraph
);
4146 vty_out(vty
, "%s\n", dot
);
4147 XFREE(MTYPE_TMP
, dot
);
4151 static void vtysh_install_default(enum node_type node
)
4153 _install_element(node
, &config_list_cmd
);
4154 _install_element(node
, &find_cmd
);
4155 _install_element(node
, &show_cli_graph_vtysh_cmd
);
4156 _install_element(node
, &vtysh_output_file_cmd
);
4157 _install_element(node
, &no_vtysh_output_file_cmd
);
4160 /* Making connection to protocol daemon. */
4161 static int vtysh_connect(struct vtysh_client
*vclient
)
4165 struct sockaddr_un addr
;
4169 if (!vclient
->path
[0])
4170 snprintf(vclient
->path
, sizeof(vclient
->path
), "%s/%s.vty",
4171 vtydir
, vclient
->name
);
4172 path
= vclient
->path
;
4174 /* Stat socket to see if we have permission to access it. */
4175 ret
= stat(path
, &s_stat
);
4176 if (ret
< 0 && errno
!= ENOENT
) {
4177 fprintf(stderr
, "vtysh_connect(%s): stat = %s\n", path
,
4178 safe_strerror(errno
));
4183 if (!S_ISSOCK(s_stat
.st_mode
)) {
4184 fprintf(stderr
, "vtysh_connect(%s): Not a socket\n",
4190 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
4193 fprintf(stderr
, "vtysh_connect(%s): socket = %s\n", path
,
4194 safe_strerror(errno
));
4199 memset(&addr
, 0, sizeof(addr
));
4200 addr
.sun_family
= AF_UNIX
;
4201 strlcpy(addr
.sun_path
, path
, sizeof(addr
.sun_path
));
4202 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
4203 len
= addr
.sun_len
= SUN_LEN(&addr
);
4205 len
= sizeof(addr
.sun_family
) + strlen(addr
.sun_path
);
4206 #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
4208 ret
= connect(sock
, (struct sockaddr
*)&addr
, len
);
4211 fprintf(stderr
, "vtysh_connect(%s): connect = %s\n", path
,
4212 safe_strerror(errno
));
4222 static int vtysh_reconnect(struct vtysh_client
*vclient
)
4226 fprintf(stderr
, "Warning: connecting to %s...", vclient
->name
);
4227 ret
= vtysh_connect(vclient
);
4229 fprintf(stderr
, "failed!\n");
4232 fprintf(stderr
, "success!\n");
4233 if (vtysh_client_execute(vclient
, "enable") < 0)
4235 return vtysh_execute_no_pager("end");
4238 /* Return true if str ends with suffix, else return false */
4239 static int ends_with(const char *str
, const char *suffix
)
4241 if (!str
|| !suffix
)
4243 size_t lenstr
= strlen(str
);
4244 size_t lensuffix
= strlen(suffix
);
4245 if (lensuffix
> lenstr
)
4247 return strncmp(str
+ lenstr
- lensuffix
, suffix
, lensuffix
) == 0;
4250 static void vtysh_client_sorted_insert(struct vtysh_client
*head_client
,
4251 struct vtysh_client
*client
)
4253 struct vtysh_client
*prev_node
, *current_node
;
4255 prev_node
= head_client
;
4256 current_node
= head_client
->next
;
4257 while (current_node
) {
4258 if (strcmp(current_node
->path
, client
->path
) > 0)
4261 prev_node
= current_node
;
4262 current_node
= current_node
->next
;
4264 client
->next
= current_node
;
4265 prev_node
->next
= client
;
4268 #define MAXIMUM_INSTANCES 10
4270 static void vtysh_update_all_instances(struct vtysh_client
*head_client
)
4272 struct vtysh_client
*client
;
4274 struct dirent
*file
;
4277 if (head_client
->flag
!= VTYSH_OSPFD
)
4280 /* ls vty_sock_dir and look for all files ending in .vty */
4281 dir
= opendir(vtydir
);
4283 while ((file
= readdir(dir
)) != NULL
) {
4284 if (frrstr_startswith(file
->d_name
, "ospfd-")
4285 && ends_with(file
->d_name
, ".vty")) {
4286 if (n
== MAXIMUM_INSTANCES
) {
4288 "Parsing %s, client limit(%d) reached!\n",
4292 client
= (struct vtysh_client
*)malloc(
4293 sizeof(struct vtysh_client
));
4295 client
->name
= "ospfd";
4296 client
->flag
= VTYSH_OSPFD
;
4297 snprintf(client
->path
, sizeof(client
->path
),
4298 "%s/%s", vtydir
, file
->d_name
);
4299 client
->next
= NULL
;
4300 vtysh_client_sorted_insert(head_client
, client
);
4308 static int vtysh_connect_all_instances(struct vtysh_client
*head_client
)
4310 struct vtysh_client
*client
;
4313 vtysh_update_all_instances(head_client
);
4315 client
= head_client
->next
;
4317 if (vtysh_connect(client
) == 0)
4319 client
= client
->next
;
4325 int vtysh_connect_all(const char *daemon_name
)
4331 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
4333 || !strcmp(daemon_name
, vtysh_client
[i
].name
)) {
4335 if (vtysh_connect(&vtysh_client
[i
]) == 0)
4338 rc
+= vtysh_connect_all_instances(&vtysh_client
[i
]);
4342 fprintf(stderr
, "Error: no daemons match name %s!\n",
4347 /* To disable readline's filename completion. */
4348 static char *vtysh_completion_entry_function(const char *ignore
,
4354 void vtysh_readline_init(void)
4356 /* readline related settings. */
4357 char *disable_bracketed_paste
=
4358 XSTRDUP(MTYPE_TMP
, "set enable-bracketed-paste off");
4361 rl_parse_and_bind(disable_bracketed_paste
);
4362 rl_bind_key('?', (rl_command_func_t
*)vtysh_rl_describe
);
4363 rl_completion_entry_function
= vtysh_completion_entry_function
;
4364 rl_attempted_completion_function
= new_completion
;
4366 XFREE(MTYPE_TMP
, disable_bracketed_paste
);
4369 char *vtysh_prompt(void)
4371 static char buf
[512];
4373 #pragma GCC diagnostic push
4374 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
4375 /* prompt formatting has a %s in the cmd_node prompt string. */
4376 snprintf(buf
, sizeof(buf
), cmd_prompt(vty
->node
), cmd_hostname_get());
4377 #pragma GCC diagnostic pop
4381 static void vtysh_ac_line(void *arg
, const char *line
)
4385 for (i
= 0; i
< vector_active(comps
); i
++)
4386 if (!strcmp(line
, (char *)vector_slot(comps
, i
)))
4388 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, line
));
4391 static void vtysh_autocomplete(vector comps
, struct cmd_token
*token
)
4396 snprintf(accmd
, sizeof(accmd
), "autocomplete %d %s %s", token
->type
,
4397 token
->text
, token
->varname
? token
->varname
: "-");
4399 vty
->of_saved
= vty
->of
;
4401 for (i
= 0; i
< array_size(vtysh_client
); i
++)
4402 vtysh_client_run_all(&vtysh_client
[i
], accmd
, 1, vtysh_ac_line
,
4404 vty
->of
= vty
->of_saved
;
4407 static const struct cmd_variable_handler vtysh_var_handler
[] = {
4411 .completions
= vtysh_autocomplete
},
4412 {.completions
= NULL
}};
4414 void vtysh_uninit(void)
4416 if (vty
->of
!= stdout
)
4420 void vtysh_init_vty(void)
4422 struct stat st_out
, st_err
;
4424 cmd_defer_tree(true);
4426 for (size_t i
= 0; i
< array_size(vtysh_client
); i
++) {
4427 vtysh_client
[i
].fd
= -1;
4428 vtysh_client
[i
].log_fd
= -1;
4431 stderr_tty
= isatty(STDERR_FILENO
);
4433 if (fstat(STDOUT_FILENO
, &st_out
) || fstat(STDERR_FILENO
, &st_err
) ||
4434 (st_out
.st_dev
== st_err
.st_dev
&& st_out
.st_ino
== st_err
.st_ino
))
4435 stderr_stdout_same
= true;
4437 /* Make vty structure. */
4439 vty
->type
= VTY_SHELL
;
4440 vty
->node
= VIEW_NODE
;
4442 /* set default output */
4444 vtysh_pager_envdef(false);
4446 /* Initialize commands. */
4448 cmd_variable_handler_register(vtysh_var_handler
);
4452 install_node(&bgp_node
);
4453 install_element(CONFIG_NODE
, &router_bgp_cmd
);
4454 install_element(BGP_NODE
, &vtysh_exit_bgpd_cmd
);
4455 install_element(BGP_NODE
, &vtysh_quit_bgpd_cmd
);
4456 install_element(BGP_NODE
, &vtysh_end_all_cmd
);
4458 install_node(&bgp_vpnv4_node
);
4459 install_element(BGP_NODE
, &address_family_ipv4_vpn_cmd
);
4460 #ifdef KEEP_OLD_VPN_COMMANDS
4461 install_element(BGP_NODE
, &address_family_vpnv4_cmd
);
4462 #endif /* KEEP_OLD_VPN_COMMANDS */
4463 install_element(BGP_VPNV4_NODE
, &vtysh_exit_bgpd_cmd
);
4464 install_element(BGP_VPNV4_NODE
, &vtysh_quit_bgpd_cmd
);
4465 install_element(BGP_VPNV4_NODE
, &vtysh_end_all_cmd
);
4466 install_element(BGP_VPNV4_NODE
, &exit_address_family_cmd
);
4468 install_node(&bgp_vpnv6_node
);
4469 install_element(BGP_NODE
, &address_family_ipv6_vpn_cmd
);
4470 #ifdef KEEP_OLD_VPN_COMMANDS
4471 install_element(BGP_NODE
, &address_family_vpnv6_cmd
);
4472 #endif /* KEEP_OLD_VPN_COMMANDS */
4473 install_element(BGP_VPNV6_NODE
, &vtysh_exit_bgpd_cmd
);
4474 install_element(BGP_VPNV6_NODE
, &vtysh_quit_bgpd_cmd
);
4475 install_element(BGP_VPNV6_NODE
, &vtysh_end_all_cmd
);
4476 install_element(BGP_VPNV6_NODE
, &exit_address_family_cmd
);
4478 install_node(&bgp_flowspecv4_node
);
4479 install_element(BGP_NODE
, &address_family_flowspecv4_cmd
);
4480 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_exit_bgpd_cmd
);
4481 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_quit_bgpd_cmd
);
4482 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_end_all_cmd
);
4483 install_element(BGP_FLOWSPECV4_NODE
, &exit_address_family_cmd
);
4485 install_node(&bgp_flowspecv6_node
);
4486 install_element(BGP_NODE
, &address_family_flowspecv6_cmd
);
4487 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_exit_bgpd_cmd
);
4488 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_quit_bgpd_cmd
);
4489 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_end_all_cmd
);
4490 install_element(BGP_FLOWSPECV6_NODE
, &exit_address_family_cmd
);
4492 install_node(&bgp_ipv4_node
);
4493 install_element(BGP_NODE
, &address_family_ipv4_cmd
);
4494 install_element(BGP_IPV4_NODE
, &vtysh_exit_bgpd_cmd
);
4495 install_element(BGP_IPV4_NODE
, &vtysh_quit_bgpd_cmd
);
4496 install_element(BGP_IPV4_NODE
, &vtysh_end_all_cmd
);
4497 install_element(BGP_IPV4_NODE
, &exit_address_family_cmd
);
4499 install_node(&bgp_ipv4m_node
);
4500 install_element(BGP_NODE
, &address_family_ipv4_multicast_cmd
);
4501 install_element(BGP_IPV4M_NODE
, &vtysh_exit_bgpd_cmd
);
4502 install_element(BGP_IPV4M_NODE
, &vtysh_quit_bgpd_cmd
);
4503 install_element(BGP_IPV4M_NODE
, &vtysh_end_all_cmd
);
4504 install_element(BGP_IPV4M_NODE
, &exit_address_family_cmd
);
4506 install_node(&bgp_ipv4l_node
);
4507 install_element(BGP_NODE
, &address_family_ipv4_labeled_unicast_cmd
);
4508 install_element(BGP_IPV4L_NODE
, &vtysh_exit_bgpd_cmd
);
4509 install_element(BGP_IPV4L_NODE
, &vtysh_quit_bgpd_cmd
);
4510 install_element(BGP_IPV4L_NODE
, &vtysh_end_all_cmd
);
4511 install_element(BGP_IPV4L_NODE
, &exit_address_family_cmd
);
4513 install_node(&bgp_ipv6_node
);
4514 install_element(BGP_NODE
, &address_family_ipv6_cmd
);
4515 install_element(BGP_IPV6_NODE
, &vtysh_exit_bgpd_cmd
);
4516 install_element(BGP_IPV6_NODE
, &vtysh_quit_bgpd_cmd
);
4517 install_element(BGP_IPV6_NODE
, &vtysh_end_all_cmd
);
4518 install_element(BGP_IPV6_NODE
, &exit_address_family_cmd
);
4520 install_node(&bgp_ipv6m_node
);
4521 install_element(BGP_NODE
, &address_family_ipv6_multicast_cmd
);
4522 install_element(BGP_IPV6M_NODE
, &vtysh_exit_bgpd_cmd
);
4523 install_element(BGP_IPV6M_NODE
, &vtysh_quit_bgpd_cmd
);
4524 install_element(BGP_IPV6M_NODE
, &vtysh_end_all_cmd
);
4525 install_element(BGP_IPV6M_NODE
, &exit_address_family_cmd
);
4527 install_node(&bgp_ipv6l_node
);
4528 install_element(BGP_NODE
, &address_family_ipv6_labeled_unicast_cmd
);
4529 install_element(BGP_IPV6L_NODE
, &vtysh_exit_bgpd_cmd
);
4530 install_element(BGP_IPV6L_NODE
, &vtysh_quit_bgpd_cmd
);
4531 install_element(BGP_IPV6L_NODE
, &vtysh_end_all_cmd
);
4532 install_element(BGP_IPV6L_NODE
, &exit_address_family_cmd
);
4534 #if defined(ENABLE_BGP_VNC)
4535 install_node(&bgp_vrf_policy_node
);
4536 install_element(BGP_NODE
, &vnc_vrf_policy_cmd
);
4537 install_element(BGP_VRF_POLICY_NODE
, &vtysh_exit_bgpd_cmd
);
4538 install_element(BGP_VRF_POLICY_NODE
, &vtysh_quit_bgpd_cmd
);
4539 install_element(BGP_VRF_POLICY_NODE
, &vtysh_end_all_cmd
);
4540 install_element(BGP_VRF_POLICY_NODE
, &exit_vrf_policy_cmd
);
4542 install_node(&bgp_vnc_defaults_node
);
4543 install_element(BGP_NODE
, &vnc_defaults_cmd
);
4544 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_exit_bgpd_cmd
);
4545 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_quit_bgpd_cmd
);
4546 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_end_all_cmd
);
4547 install_element(BGP_VNC_DEFAULTS_NODE
, &exit_vnc_config_cmd
);
4549 install_node(&bgp_vnc_nve_group_node
);
4550 install_element(BGP_NODE
, &vnc_nve_group_cmd
);
4551 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4552 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4553 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_end_all_cmd
);
4554 install_element(BGP_VNC_NVE_GROUP_NODE
, &exit_vnc_config_cmd
);
4556 install_node(&bgp_vnc_l2_group_node
);
4557 install_element(BGP_NODE
, &vnc_l2_group_cmd
);
4558 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4559 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4560 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_end_all_cmd
);
4561 install_element(BGP_VNC_L2_GROUP_NODE
, &exit_vnc_config_cmd
);
4564 install_node(&bgp_evpn_node
);
4565 install_element(BGP_NODE
, &address_family_evpn_cmd
);
4566 install_element(BGP_EVPN_NODE
, &vtysh_quit_bgpd_cmd
);
4567 install_element(BGP_EVPN_NODE
, &vtysh_exit_bgpd_cmd
);
4568 install_element(BGP_EVPN_NODE
, &vtysh_end_all_cmd
);
4569 install_element(BGP_EVPN_NODE
, &exit_address_family_cmd
);
4571 install_node(&bgp_evpn_vni_node
);
4572 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
4573 install_element(BGP_EVPN_VNI_NODE
, &vtysh_exit_bgpd_cmd
);
4574 install_element(BGP_EVPN_VNI_NODE
, &vtysh_quit_bgpd_cmd
);
4575 install_element(BGP_EVPN_VNI_NODE
, &vtysh_end_all_cmd
);
4576 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
4578 install_node(&rpki_node
);
4579 install_element(CONFIG_NODE
, &rpki_cmd
);
4580 install_element(RPKI_NODE
, &rpki_exit_cmd
);
4581 install_element(RPKI_NODE
, &rpki_quit_cmd
);
4582 install_element(RPKI_NODE
, &vtysh_end_all_cmd
);
4584 install_node(&bmp_node
);
4585 install_element(BGP_NODE
, &bmp_targets_cmd
);
4586 install_element(BMP_NODE
, &bmp_exit_cmd
);
4587 install_element(BMP_NODE
, &bmp_quit_cmd
);
4588 install_element(BMP_NODE
, &vtysh_end_all_cmd
);
4590 install_node(&bgp_srv6_node
);
4591 install_element(BGP_NODE
, &bgp_srv6_cmd
);
4592 install_element(BGP_SRV6_NODE
, &exit_bgp_srv6_cmd
);
4593 install_element(BGP_SRV6_NODE
, &quit_bgp_srv6_cmd
);
4594 install_element(BGP_SRV6_NODE
, &vtysh_end_all_cmd
);
4595 #endif /* HAVE_BGPD */
4598 install_node(&rip_node
);
4600 install_element(CONFIG_NODE
, &router_rip_cmd
);
4601 install_element(RIP_NODE
, &vtysh_exit_ripd_cmd
);
4602 install_element(RIP_NODE
, &vtysh_quit_ripd_cmd
);
4603 install_element(RIP_NODE
, &vtysh_end_all_cmd
);
4604 #endif /* HAVE_RIPD */
4607 install_node(&ripng_node
);
4609 install_element(CONFIG_NODE
, &router_ripng_cmd
);
4610 install_element(RIPNG_NODE
, &vtysh_exit_ripngd_cmd
);
4611 install_element(RIPNG_NODE
, &vtysh_quit_ripngd_cmd
);
4612 install_element(RIPNG_NODE
, &vtysh_end_all_cmd
);
4613 #endif /* HAVE_RIPNGD */
4617 install_node(&ospf_node
);
4618 install_element(CONFIG_NODE
, &router_ospf_cmd
);
4619 install_element(OSPF_NODE
, &vtysh_exit_ospfd_cmd
);
4620 install_element(OSPF_NODE
, &vtysh_quit_ospfd_cmd
);
4621 install_element(OSPF_NODE
, &vtysh_end_all_cmd
);
4622 #endif /* HAVE_OSPFD */
4626 install_node(&ospf6_node
);
4627 install_element(CONFIG_NODE
, &router_ospf6_cmd
);
4628 install_element(OSPF6_NODE
, &vtysh_exit_ospf6d_cmd
);
4629 install_element(OSPF6_NODE
, &vtysh_quit_ospf6d_cmd
);
4630 install_element(OSPF6_NODE
, &vtysh_end_all_cmd
);
4631 #endif /* HAVE_OSPF6D */
4634 #if defined(HAVE_LDPD)
4635 install_node(&ldp_node
);
4636 install_element(CONFIG_NODE
, &ldp_mpls_ldp_cmd
);
4637 install_element(LDP_NODE
, &vtysh_exit_ldpd_cmd
);
4638 install_element(LDP_NODE
, &vtysh_quit_ldpd_cmd
);
4639 install_element(LDP_NODE
, &vtysh_end_all_cmd
);
4641 install_node(&ldp_ipv4_node
);
4642 install_element(LDP_NODE
, &ldp_address_family_ipv4_cmd
);
4643 install_element(LDP_IPV4_NODE
, &vtysh_exit_ldpd_cmd
);
4644 install_element(LDP_IPV4_NODE
, &vtysh_quit_ldpd_cmd
);
4645 install_element(LDP_IPV4_NODE
, &ldp_exit_address_family_cmd
);
4646 install_element(LDP_IPV4_NODE
, &vtysh_end_all_cmd
);
4648 install_node(&ldp_ipv6_node
);
4649 install_element(LDP_NODE
, &ldp_address_family_ipv6_cmd
);
4650 install_element(LDP_IPV6_NODE
, &vtysh_exit_ldpd_cmd
);
4651 install_element(LDP_IPV6_NODE
, &vtysh_quit_ldpd_cmd
);
4652 install_element(LDP_IPV6_NODE
, &ldp_exit_address_family_cmd
);
4653 install_element(LDP_IPV6_NODE
, &vtysh_end_all_cmd
);
4655 install_node(&ldp_ipv4_iface_node
);
4656 install_element(LDP_IPV4_NODE
, &ldp_interface_ifname_cmd
);
4657 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4658 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4659 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_end_all_cmd
);
4661 install_node(&ldp_ipv6_iface_node
);
4662 install_element(LDP_IPV6_NODE
, &ldp_interface_ifname_cmd
);
4663 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4664 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4665 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_end_all_cmd
);
4667 install_node(&ldp_l2vpn_node
);
4668 install_element(CONFIG_NODE
, &ldp_l2vpn_word_type_vpls_cmd
);
4669 install_element(LDP_L2VPN_NODE
, &vtysh_exit_ldpd_cmd
);
4670 install_element(LDP_L2VPN_NODE
, &vtysh_quit_ldpd_cmd
);
4671 install_element(LDP_L2VPN_NODE
, &vtysh_end_all_cmd
);
4673 install_node(&ldp_pseudowire_node
);
4674 install_element(LDP_L2VPN_NODE
, &ldp_member_pseudowire_ifname_cmd
);
4675 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_exit_ldpd_cmd
);
4676 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_quit_ldpd_cmd
);
4677 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_end_all_cmd
);
4682 install_node(&eigrp_node
);
4683 install_element(CONFIG_NODE
, &router_eigrp_cmd
);
4684 install_element(EIGRP_NODE
, &vtysh_exit_eigrpd_cmd
);
4685 install_element(EIGRP_NODE
, &vtysh_quit_eigrpd_cmd
);
4686 install_element(EIGRP_NODE
, &vtysh_end_all_cmd
);
4687 #endif /* HAVE_EIGRPD */
4691 install_node(&babel_node
);
4692 install_element(CONFIG_NODE
, &router_babel_cmd
);
4693 install_element(BABEL_NODE
, &vtysh_exit_babeld_cmd
);
4694 install_element(BABEL_NODE
, &vtysh_quit_babeld_cmd
);
4695 install_element(BABEL_NODE
, &vtysh_end_all_cmd
);
4696 #endif /* HAVE_BABELD */
4700 install_node(&isis_node
);
4701 install_element(CONFIG_NODE
, &router_isis_cmd
);
4702 install_element(ISIS_NODE
, &vtysh_exit_isisd_cmd
);
4703 install_element(ISIS_NODE
, &vtysh_quit_isisd_cmd
);
4704 install_element(ISIS_NODE
, &vtysh_end_all_cmd
);
4705 #endif /* HAVE_ISISD */
4709 install_node(&openfabric_node
);
4710 install_element(CONFIG_NODE
, &router_openfabric_cmd
);
4711 install_element(OPENFABRIC_NODE
, &vtysh_exit_fabricd_cmd
);
4712 install_element(OPENFABRIC_NODE
, &vtysh_quit_fabricd_cmd
);
4713 install_element(OPENFABRIC_NODE
, &vtysh_end_all_cmd
);
4714 #endif /* HAVE_FABRICD */
4718 install_node(&pbr_map_node
);
4719 install_element(CONFIG_NODE
, &vtysh_pbr_map_cmd
);
4720 install_element(CONFIG_NODE
, &vtysh_no_pbr_map_cmd
);
4721 install_element(PBRMAP_NODE
, &vtysh_exit_pbr_map_cmd
);
4722 install_element(PBRMAP_NODE
, &vtysh_quit_pbr_map_cmd
);
4723 install_element(PBRMAP_NODE
, &vtysh_end_all_cmd
);
4724 #endif /* HAVE_PBRD */
4728 install_node(&bfd_node
);
4729 install_element(CONFIG_NODE
, &bfd_enter_cmd
);
4730 install_element(BFD_NODE
, &vtysh_exit_bfdd_cmd
);
4731 install_element(BFD_NODE
, &vtysh_quit_bfdd_cmd
);
4732 install_element(BFD_NODE
, &vtysh_end_all_cmd
);
4734 install_node(&bfd_peer_node
);
4735 install_element(BFD_NODE
, &bfd_peer_enter_cmd
);
4736 install_element(BFD_PEER_NODE
, &vtysh_exit_bfdd_cmd
);
4737 install_element(BFD_PEER_NODE
, &vtysh_quit_bfdd_cmd
);
4738 install_element(BFD_PEER_NODE
, &vtysh_end_all_cmd
);
4740 install_node(&bfd_profile_node
);
4741 install_element(BFD_NODE
, &bfd_profile_enter_cmd
);
4742 install_element(BFD_PROFILE_NODE
, &vtysh_exit_bfdd_cmd
);
4743 install_element(BFD_PROFILE_NODE
, &vtysh_quit_bfdd_cmd
);
4744 install_element(BFD_PROFILE_NODE
, &vtysh_end_all_cmd
);
4745 #endif /* HAVE_BFDD */
4747 install_node(&segment_routing_node
);
4748 install_element(CONFIG_NODE
, &segment_routing_cmd
);
4749 install_element(SEGMENT_ROUTING_NODE
, &vtysh_exit_sr_cmd
);
4750 install_element(SEGMENT_ROUTING_NODE
, &vtysh_quit_sr_cmd
);
4751 install_element(SEGMENT_ROUTING_NODE
, &vtysh_end_all_cmd
);
4753 #if defined(HAVE_PATHD)
4754 install_node(&sr_traffic_eng_node
);
4755 install_node(&srte_segment_list_node
);
4756 install_node(&srte_policy_node
);
4757 install_node(&srte_candidate_dyn_node
);
4759 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_exit_pathd_cmd
);
4760 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_quit_pathd_cmd
);
4761 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_exit_pathd_cmd
);
4762 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_quit_pathd_cmd
);
4763 install_element(SR_POLICY_NODE
, &vtysh_exit_pathd_cmd
);
4764 install_element(SR_POLICY_NODE
, &vtysh_quit_pathd_cmd
);
4765 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_exit_pathd_cmd
);
4766 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_quit_pathd_cmd
);
4769 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_end_all_cmd
);
4770 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_end_all_cmd
);
4771 install_element(SR_POLICY_NODE
, &vtysh_end_all_cmd
);
4772 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_end_all_cmd
);
4774 install_element(SEGMENT_ROUTING_NODE
, &sr_traffic_eng_cmd
);
4775 install_element(SR_TRAFFIC_ENG_NODE
, &srte_segment_list_cmd
);
4776 install_element(SR_TRAFFIC_ENG_NODE
, &srte_policy_cmd
);
4777 install_element(SR_POLICY_NODE
, &srte_policy_candidate_dyn_path_cmd
);
4779 install_node(&pcep_node
);
4780 install_node(&pcep_pcc_node
);
4781 install_node(&pcep_pce_node
);
4782 install_node(&pcep_pce_config_node
);
4784 install_element(PCEP_NODE
, &vtysh_exit_pathd_cmd
);
4785 install_element(PCEP_NODE
, &vtysh_quit_pathd_cmd
);
4786 install_element(PCEP_PCC_NODE
, &vtysh_exit_pathd_cmd
);
4787 install_element(PCEP_PCC_NODE
, &vtysh_quit_pathd_cmd
);
4788 install_element(PCEP_PCE_NODE
, &vtysh_exit_pathd_cmd
);
4789 install_element(PCEP_PCE_NODE
, &vtysh_quit_pathd_cmd
);
4790 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_exit_pathd_cmd
);
4791 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_quit_pathd_cmd
);
4793 install_element(PCEP_NODE
, &vtysh_end_all_cmd
);
4794 install_element(PCEP_PCC_NODE
, &vtysh_end_all_cmd
);
4795 install_element(PCEP_PCE_NODE
, &vtysh_end_all_cmd
);
4796 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_end_all_cmd
);
4798 install_element(SR_TRAFFIC_ENG_NODE
, &pcep_cmd
);
4799 install_element(PCEP_NODE
, &pcep_cli_pcc_cmd
);
4800 install_element(PCEP_NODE
, &pcep_cli_pcep_pce_config_cmd
);
4801 install_element(PCEP_NODE
, &pcep_cli_pce_cmd
);
4803 #endif /* HAVE_PATHD */
4806 install_node(&keychain_node
);
4807 install_element(CONFIG_NODE
, &key_chain_cmd
);
4808 install_element(KEYCHAIN_NODE
, &key_chain_cmd
);
4809 install_element(KEYCHAIN_NODE
, &vtysh_exit_keys_cmd
);
4810 install_element(KEYCHAIN_NODE
, &vtysh_quit_keys_cmd
);
4811 install_element(KEYCHAIN_NODE
, &vtysh_end_all_cmd
);
4813 install_node(&keychain_key_node
);
4814 install_element(KEYCHAIN_NODE
, &key_cmd
);
4815 install_element(KEYCHAIN_KEY_NODE
, &key_chain_cmd
);
4816 install_element(KEYCHAIN_KEY_NODE
, &vtysh_exit_keys_cmd
);
4817 install_element(KEYCHAIN_KEY_NODE
, &vtysh_quit_keys_cmd
);
4818 install_element(KEYCHAIN_KEY_NODE
, &vtysh_end_all_cmd
);
4821 install_node(&nh_group_node
);
4822 install_element(CONFIG_NODE
, &vtysh_nexthop_group_cmd
);
4823 install_element(CONFIG_NODE
, &vtysh_no_nexthop_group_cmd
);
4824 install_element(NH_GROUP_NODE
, &vtysh_end_all_cmd
);
4825 install_element(NH_GROUP_NODE
, &vtysh_exit_nexthop_group_cmd
);
4826 install_element(NH_GROUP_NODE
, &vtysh_quit_nexthop_group_cmd
);
4829 install_node(&zebra_node
);
4831 install_node(&interface_node
);
4832 install_element(CONFIG_NODE
, &vtysh_interface_cmd
);
4833 install_element(INTERFACE_NODE
, &vtysh_end_all_cmd
);
4834 install_element(INTERFACE_NODE
, &vtysh_exit_interface_cmd
);
4835 install_element(INTERFACE_NODE
, &vtysh_quit_interface_cmd
);
4837 install_node(&link_params_node
);
4838 install_element(INTERFACE_NODE
, &vtysh_link_params_cmd
);
4839 install_element(LINK_PARAMS_NODE
, &exit_link_params_cmd
);
4840 install_element(LINK_PARAMS_NODE
, &vtysh_end_all_cmd
);
4841 install_element(LINK_PARAMS_NODE
, &vtysh_exit_link_params_cmd
);
4842 install_element(LINK_PARAMS_NODE
, &vtysh_quit_link_params_cmd
);
4844 install_node(&pw_node
);
4845 install_element(CONFIG_NODE
, &vtysh_pseudowire_cmd
);
4846 install_element(PW_NODE
, &vtysh_end_all_cmd
);
4847 install_element(PW_NODE
, &vtysh_exit_pseudowire_cmd
);
4848 install_element(PW_NODE
, &vtysh_quit_pseudowire_cmd
);
4850 install_node(&vrf_node
);
4851 install_element(CONFIG_NODE
, &vtysh_vrf_cmd
);
4852 install_element(VRF_NODE
, &exit_vrf_config_cmd
);
4853 install_element(VRF_NODE
, &vtysh_end_all_cmd
);
4854 install_element(VRF_NODE
, &vtysh_exit_vrf_cmd
);
4855 install_element(VRF_NODE
, &vtysh_quit_vrf_cmd
);
4857 install_element(CONFIG_NODE
, &vtysh_affinity_map_cmd
);
4858 install_element(CONFIG_NODE
, &vtysh_no_affinity_map_cmd
);
4860 install_node(&rmap_node
);
4861 install_element(CONFIG_NODE
, &vtysh_route_map_cmd
);
4862 install_element(RMAP_NODE
, &vtysh_exit_rmap_cmd
);
4863 install_element(RMAP_NODE
, &vtysh_quit_rmap_cmd
);
4864 install_element(RMAP_NODE
, &vtysh_end_all_cmd
);
4866 install_node(&vty_node
);
4867 install_element(CONFIG_NODE
, &vtysh_line_vty_cmd
);
4868 install_element(VTY_NODE
, &vtysh_exit_line_vty_cmd
);
4869 install_element(VTY_NODE
, &vtysh_quit_line_vty_cmd
);
4870 install_element(VTY_NODE
, &vtysh_end_all_cmd
);
4873 struct cmd_node
*node
;
4874 for (unsigned int i
= 0; i
< vector_active(cmdvec
); i
++) {
4875 node
= vector_slot(cmdvec
, i
);
4876 if (!node
|| node
->node
== VIEW_NODE
)
4878 vtysh_install_default(node
->node
);
4884 install_element(VIEW_NODE
, &vtysh_enable_cmd
);
4885 install_element(ENABLE_NODE
, &vtysh_config_terminal_cmd
);
4886 install_element(ENABLE_NODE
, &vtysh_disable_cmd
);
4888 /* "exit" command. */
4889 install_element(VIEW_NODE
, &vtysh_exit_all_cmd
);
4890 install_element(CONFIG_NODE
, &vtysh_exit_all_cmd
);
4891 install_element(VIEW_NODE
, &vtysh_quit_all_cmd
);
4892 install_element(CONFIG_NODE
, &vtysh_quit_all_cmd
);
4894 /* "end" command. */
4895 install_element(CONFIG_NODE
, &vtysh_end_all_cmd
);
4896 install_element(ENABLE_NODE
, &vtysh_end_all_cmd
);
4898 /* SRv6 Data-plane */
4899 install_node(&srv6_node
);
4900 install_element(SEGMENT_ROUTING_NODE
, &srv6_cmd
);
4901 install_element(SRV6_NODE
, &srv6_locators_cmd
);
4902 install_element(SRV6_NODE
, &exit_srv6_config_cmd
);
4903 install_element(SRV6_NODE
, &vtysh_end_all_cmd
);
4905 install_node(&srv6_locs_node
);
4906 install_element(SRV6_LOCS_NODE
, &srv6_locator_cmd
);
4907 install_element(SRV6_LOCS_NODE
, &exit_srv6_locs_config_cmd
);
4908 install_element(SRV6_LOCS_NODE
, &vtysh_end_all_cmd
);
4910 install_node(&srv6_loc_node
);
4911 install_element(SRV6_LOC_NODE
, &exit_srv6_loc_config_cmd
);
4912 install_element(SRV6_LOC_NODE
, &vtysh_end_all_cmd
);
4914 install_element(ENABLE_NODE
, &vtysh_show_running_config_cmd
);
4915 install_element(ENABLE_NODE
, &vtysh_copy_running_config_cmd
);
4916 install_element(ENABLE_NODE
, &vtysh_copy_to_running_cmd
);
4918 /* "write terminal" command. */
4919 install_element(ENABLE_NODE
, &vtysh_write_terminal_cmd
);
4921 install_element(CONFIG_NODE
, &vtysh_integrated_config_cmd
);
4922 install_element(CONFIG_NODE
, &no_vtysh_integrated_config_cmd
);
4924 /* "write memory" command. */
4925 install_element(ENABLE_NODE
, &vtysh_write_memory_cmd
);
4927 install_element(CONFIG_NODE
, &start_config_cmd
);
4928 install_element(CONFIG_NODE
, &end_config_cmd
);
4930 install_element(CONFIG_NODE
, &vtysh_terminal_paginate_cmd
);
4931 install_element(VIEW_NODE
, &vtysh_terminal_paginate_cmd
);
4932 install_element(VIEW_NODE
, &vtysh_terminal_length_cmd
);
4933 install_element(VIEW_NODE
, &vtysh_terminal_no_length_cmd
);
4934 install_element(VIEW_NODE
, &vtysh_show_daemons_cmd
);
4936 install_element(VIEW_NODE
, &vtysh_terminal_monitor_cmd
);
4937 install_element(VIEW_NODE
, &no_vtysh_terminal_monitor_cmd
);
4939 install_element(VIEW_NODE
, &vtysh_ping_cmd
);
4940 install_element(VIEW_NODE
, &vtysh_motd_cmd
);
4941 install_element(VIEW_NODE
, &vtysh_ping_ip_cmd
);
4942 install_element(VIEW_NODE
, &vtysh_traceroute_cmd
);
4943 install_element(VIEW_NODE
, &vtysh_traceroute_ip_cmd
);
4944 install_element(VIEW_NODE
, &vtysh_mtrace_cmd
);
4945 install_element(VIEW_NODE
, &vtysh_ping6_cmd
);
4946 install_element(VIEW_NODE
, &vtysh_traceroute6_cmd
);
4947 #if defined(HAVE_SHELL_ACCESS)
4948 install_element(VIEW_NODE
, &vtysh_telnet_cmd
);
4949 install_element(VIEW_NODE
, &vtysh_telnet_port_cmd
);
4950 install_element(VIEW_NODE
, &vtysh_ssh_cmd
);
4952 #if defined(HAVE_SHELL_ACCESS)
4953 install_element(ENABLE_NODE
, &vtysh_start_shell_cmd
);
4954 install_element(ENABLE_NODE
, &vtysh_start_bash_cmd
);
4955 install_element(ENABLE_NODE
, &vtysh_start_zsh_cmd
);
4959 install_element(VIEW_NODE
, &vtysh_show_error_code_cmd
);
4960 install_element(ENABLE_NODE
, &vtysh_show_debugging_cmd
);
4961 install_element(ENABLE_NODE
, &vtysh_show_debugging_hashtable_cmd
);
4962 install_element(ENABLE_NODE
, &vtysh_debug_all_cmd
);
4963 install_element(CONFIG_NODE
, &vtysh_debug_all_cmd
);
4964 install_element(ENABLE_NODE
, &vtysh_debug_memstats_cmd
);
4965 install_element(CONFIG_NODE
, &vtysh_debug_memstats_cmd
);
4966 install_element(ENABLE_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4967 install_element(CONFIG_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4970 install_element(ENABLE_NODE
, &show_config_running_cmd
);
4971 install_element(ENABLE_NODE
, &show_yang_operational_data_cmd
);
4972 install_element(ENABLE_NODE
, &show_yang_module_cmd
);
4973 install_element(ENABLE_NODE
, &show_yang_module_detail_cmd
);
4974 install_element(ENABLE_NODE
, &debug_nb_cmd
);
4975 install_element(CONFIG_NODE
, &debug_nb_cmd
);
4977 /* misc lib show commands */
4978 install_element(VIEW_NODE
, &vtysh_show_history_cmd
);
4979 install_element(VIEW_NODE
, &vtysh_show_memory_cmd
);
4980 install_element(VIEW_NODE
, &vtysh_show_modules_cmd
);
4981 install_element(VIEW_NODE
, &vtysh_show_work_queues_cmd
);
4982 install_element(VIEW_NODE
, &vtysh_show_work_queues_daemon_cmd
);
4983 install_element(VIEW_NODE
, &vtysh_show_thread_cmd
);
4984 install_element(VIEW_NODE
, &vtysh_show_poll_cmd
);
4985 install_element(VIEW_NODE
, &vtysh_show_thread_timer_cmd
);
4988 install_element(VIEW_NODE
, &vtysh_show_logging_cmd
);
4990 install_element(CONFIG_NODE
, &vtysh_service_password_encrypt_cmd
);
4991 install_element(CONFIG_NODE
, &no_vtysh_service_password_encrypt_cmd
);
4993 install_element(CONFIG_NODE
, &vtysh_allow_reserved_ranges_cmd
);
4994 install_element(CONFIG_NODE
, &no_vtysh_allow_reserved_ranges_cmd
);
4996 install_element(CONFIG_NODE
, &vtysh_password_cmd
);
4997 install_element(CONFIG_NODE
, &no_vtysh_password_cmd
);
4998 install_element(CONFIG_NODE
, &vtysh_enable_password_cmd
);
4999 install_element(CONFIG_NODE
, &no_vtysh_enable_password_cmd
);