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 /* VTY shell client structure */
57 char path
[MAXPATHLEN
];
58 struct vtysh_client
*next
;
60 struct thread
*log_reader
;
65 static bool stderr_tty
;
66 static bool stderr_stdout_same
;
68 /* Some utility functions for working on vtysh-specific vty tasks */
70 static FILE *vty_open_pager(struct vty
*vty
)
75 if (!vtysh_pager_name
)
78 vty
->of_saved
= vty
->of
;
79 vty
->of
= popen(vtysh_pager_name
, "w");
80 if (vty
->of
== NULL
) {
81 vty
->of
= vty
->of_saved
;
91 static int vty_close_pager(struct vty
*vty
)
97 if (pclose(vty
->of
) == -1) {
102 vty
->of
= vty
->of_saved
;
103 vty
->is_paged
= false;
108 static void vtysh_pager_envdef(bool fallback
)
112 pager_defined
= getenv("VTYSH_PAGER");
115 vtysh_pager_name
= strdup(pager_defined
);
117 vtysh_pager_name
= strdup(VTYSH_PAGER
);
122 struct vtysh_client vtysh_client
[] = {
123 {.name
= "mgmtd", .flag
= VTYSH_MGMTD
},
124 {.name
= "zebra", .flag
= VTYSH_ZEBRA
},
125 {.name
= "ripd", .flag
= VTYSH_RIPD
},
126 {.name
= "ripngd", .flag
= VTYSH_RIPNGD
},
127 {.name
= "ospfd", .flag
= VTYSH_OSPFD
},
128 {.name
= "ospf6d", .flag
= VTYSH_OSPF6D
},
129 {.name
= "ldpd", .flag
= VTYSH_LDPD
},
130 {.name
= "bgpd", .flag
= VTYSH_BGPD
},
131 {.name
= "isisd", .flag
= VTYSH_ISISD
},
132 {.name
= "pimd", .flag
= VTYSH_PIMD
},
133 {.name
= "nhrpd", .flag
= VTYSH_NHRPD
},
134 {.name
= "eigrpd", .flag
= VTYSH_EIGRPD
},
135 {.name
= "babeld", .flag
= VTYSH_BABELD
},
136 {.name
= "sharpd", .flag
= VTYSH_SHARPD
},
137 {.name
= "fabricd", .flag
= VTYSH_FABRICD
},
138 {.name
= "watchfrr", .flag
= VTYSH_WATCHFRR
},
139 {.name
= "pbrd", .flag
= VTYSH_PBRD
},
140 {.name
= "staticd", .flag
= VTYSH_STATICD
},
141 {.name
= "bfdd", .flag
= VTYSH_BFDD
},
142 {.name
= "vrrpd", .flag
= VTYSH_VRRPD
},
143 {.name
= "pathd", .flag
= VTYSH_PATHD
},
144 {.name
= "pim6d", .flag
= VTYSH_PIM6D
},
147 /* Searches for client by name, returns index */
148 static int vtysh_client_lookup(const char *name
)
152 for (unsigned int i
= 0; i
< array_size(vtysh_client
); i
++) {
153 if (strmatch(vtysh_client
[i
].name
, name
)) {
162 enum vtysh_write_integrated vtysh_write_integrated
=
163 WRITE_INTEGRATED_UNSPECIFIED
;
165 static int vtysh_reconnect(struct vtysh_client
*vclient
);
167 static void vclient_close(struct vtysh_client
*vclient
)
169 if (vclient
->fd
>= 0) {
172 "Warning: closing connection to %s because of an I/O error!\n",
175 /* indicate as candidate for reconnect */
176 vclient
->fd
= VTYSH_WAS_ACTIVE
;
180 static ssize_t
vtysh_client_receive(struct vtysh_client
*vclient
, char *buf
,
181 size_t bufsz
, int *pass_fd
)
183 struct iovec iov
[1] = {
190 uint8_t buf
[CMSG_SPACE(sizeof(int))];
191 struct cmsghdr align
;
195 .msg_iovlen
= array_size(iov
),
196 .msg_control
= u
.buf
,
197 .msg_controllen
= sizeof(u
.buf
),
199 struct cmsghdr
*cmh
= CMSG_FIRSTHDR(&mh
);
202 cmh
->cmsg_level
= SOL_SOCKET
;
203 cmh
->cmsg_type
= SCM_RIGHTS
;
204 cmh
->cmsg_len
= CMSG_LEN(sizeof(int));
205 memset(CMSG_DATA(cmh
), -1, sizeof(int));
208 ret
= recvmsg(vclient
->fd
, &mh
, 0);
209 if (ret
>= 0 || (errno
!= EINTR
&& errno
!= EAGAIN
))
213 if (cmh
->cmsg_len
== CMSG_LEN(sizeof(int))) {
216 memcpy(&fd
, CMSG_DATA(cmh
), sizeof(int));
228 * Send a CLI command to a client and read the response.
230 * Output will be printed to vty->of. If you want to suppress output, set that
234 * the client to send the command to
237 * the command to send
240 * if non-null, this will be called with each line of output received from
241 * the client passed in the second parameter
244 * optional first argument to pass to callback
249 static int vtysh_client_run(struct vtysh_client
*vclient
, const char *line
,
250 void (*callback
)(void *, const char *), void *cbarg
,
255 char *buf
= stackbuf
;
256 size_t bufsz
= sizeof(stackbuf
);
257 char *bufvalid
, *end
= NULL
;
258 char terminator
[3] = {0, 0, 0};
260 /* vclinet was previously active, try to reconnect */
261 if (vclient
->fd
== VTYSH_WAS_ACTIVE
) {
262 ret
= vtysh_reconnect(vclient
);
270 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
272 /* close connection and try to reconnect */
273 vclient_close(vclient
);
274 ret
= vtysh_reconnect(vclient
);
278 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
287 nread
= vtysh_client_receive(
288 vclient
, bufvalid
, buf
+ bufsz
- bufvalid
- 1, pass_fd
);
290 if (nread
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
296 "vtysh: error reading from %s: %s (%d)",
297 vclient
->name
, safe_strerror(errno
),
304 /* Null terminate so we may pass this to *printf later. */
308 * We expect string output from daemons, so instead of looking
309 * for the full 3 null bytes of the terminator, we check for
310 * just one instead and assume it is the first byte of the
311 * terminator. The presence of the full terminator is checked
314 if (bufvalid
- buf
>= 4)
315 end
= memmem(bufvalid
- 4, 4, "\0", 1);
318 * calculate # bytes we have, up to & not including the
319 * terminator if present
321 size_t textlen
= (end
? end
: bufvalid
) - buf
;
324 /* feed line processing callback if present */
325 while (callback
&& bufvalid
> buf
&& (end
> buf
|| !end
)) {
326 textlen
= (end
? end
: bufvalid
) - buf
;
327 char *eol
= memchr(buf
, '\n', textlen
);
333 * no line break, end of input, no text left
334 * before end; nothing to write
338 /* no nl, end of input, but some text left */
340 else if (bufvalid
== buf
+ bufsz
- 1) {
342 * no nl, no end of input, no buffer space;
348 if (buf
== stackbuf
) {
349 new = XMALLOC(MTYPE_TMP
, bufsz
);
350 memcpy(new, stackbuf
, sizeof(stackbuf
));
352 new = XREALLOC(MTYPE_TMP
, buf
, bufsz
);
354 bufvalid
= bufvalid
- buf
+ new;
356 /* if end != NULL, we won't be reading more
366 /* eol is at line end now, either \n => \0 or \0\0\0 */
367 assert(eol
&& eol
<= bufvalid
);
370 vty_out(vty
, "%s\n", buf
);
372 callback(cbarg
, buf
);
374 /* shift back data and adjust bufvalid */
375 memmove(buf
, eol
, bufvalid
- eol
);
376 bufvalid
-= eol
- buf
;
381 /* else if no callback, dump raw */
384 vty_out(vty
, "%s", buf
);
385 memmove(buf
, buf
+ textlen
, bufvalid
- buf
- textlen
);
391 * ----------------------------------------------------
392 * At this point `buf` should be in one of two states:
393 * - Empty (i.e. buf == bufvalid)
394 * - Contains up to 4 bytes of the terminator
395 * ----------------------------------------------------
397 assert(((buf
== bufvalid
)
398 || (bufvalid
- buf
<= 4 && buf
[0] == 0x00)));
401 /* if we have the terminator, break */
402 if (end
&& bufvalid
- buf
== 4) {
403 assert(!memcmp(buf
, terminator
, 3));
412 vclient_close(vclient
);
416 XFREE(MTYPE_TMP
, buf
);
420 static int vtysh_client_run_all(struct vtysh_client
*head_client
,
421 const char *line
, int continue_on_err
,
422 void (*callback
)(void *, const char *),
425 struct vtysh_client
*client
;
426 int rc
, rc_all
= CMD_SUCCESS
;
427 int correct_instance
= 0, wrong_instance
= 0;
429 for (client
= head_client
; client
; client
= client
->next
) {
430 rc
= vtysh_client_run(client
, line
, callback
, cbarg
, NULL
);
431 if (rc
== CMD_NOT_MY_INSTANCE
) {
437 if (rc
!= CMD_SUCCESS
) {
438 if (!continue_on_err
)
443 if (wrong_instance
&& !correct_instance
&& vty
->of
) {
445 "%% [%s]: command ignored as it targets an instance that is not running\n",
447 rc_all
= CMD_WARNING_CONFIG_FAILED
;
453 * Execute command against all daemons.
456 * where to start walking in the daemon list
459 * the specific command to execute
464 static int vtysh_client_execute(struct vtysh_client
*head_client
,
467 return vtysh_client_run_all(head_client
, line
, 0, NULL
, NULL
);
470 /* Execute by name */
471 static int vtysh_client_execute_name(const char *name
, const char *line
)
473 int ret
= CMD_SUCCESS
;
476 idx_client
= vtysh_client_lookup(name
);
477 if (idx_client
!= -1)
478 ret
= vtysh_client_execute(&vtysh_client
[idx_client
], line
);
480 vty_out(vty
, "Client not found\n");
488 * Retrieve all running config from daemons and parse it with the vtysh config
489 * parser. Returned output is not displayed to the user.
492 * where to start walking in the daemon list
495 * the specific command to execute
497 static void vtysh_client_config(struct vtysh_client
*head_client
, char *line
)
499 /* watchfrr currently doesn't load any config, and has some hardcoded
500 * settings that show up in "show run". skip it here (for now at
501 * least) so we don't get that mangled up in config-write.
503 if (head_client
->flag
== VTYSH_WATCHFRR
)
506 /* suppress output to user */
507 vty
->of_saved
= vty
->of
;
509 vtysh_client_run_all(head_client
, line
, 1, vtysh_config_parse_line
,
511 vty
->of
= vty
->of_saved
;
514 /* Command execution over the vty interface. */
515 static int vtysh_execute_func(const char *line
, int pager
)
520 const struct cmd_element
*cmd
;
522 int saved_ret
, saved_node
;
524 /* Split readline string up into the vector. */
525 vline
= cmd_make_strvec(line
);
530 if (vtysh_add_timestamp
&& strncmp(line
, "exit", 4)) {
533 (void)frr_timestamp(3, ts
, sizeof(ts
));
534 vty_out(vty
, "%% %s\n\n", ts
);
537 saved_ret
= ret
= cmd_execute(vty
, line
, &cmd
, 1);
538 saved_node
= vty
->node
;
541 * If command doesn't succeeded in current node, try to walk up in node
542 * tree. Changing vty->node is enough to try it just out without actual
543 * walkup in the vtysh.
545 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
546 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
547 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
548 && vty
->node
> CONFIG_NODE
) {
549 vty
->node
= node_parent(vty
->node
);
550 ret
= cmd_execute(vty
, line
, &cmd
, 1);
554 vty
->node
= saved_node
;
557 * If command succeeded in any other node than current (tried > 0) we
558 * have to move into node in the vtysh where it succeeded.
560 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
561 || ret
== CMD_WARNING
) {
563 vtysh_execute("exit");
566 * If command didn't succeed in any node, continue with return value
573 cmd_free_strvec(vline
);
578 case CMD_WARNING_CONFIG_FAILED
:
579 if (vty
->type
== VTY_FILE
)
580 vty_out(vty
, "Warning...\n");
582 case CMD_ERR_AMBIGUOUS
:
583 vty_out(vty
, "%% Ambiguous command: %s\n", line
);
585 case CMD_ERR_NO_MATCH
:
586 vty_out(vty
, "%% Unknown command: %s\n", line
);
588 case CMD_ERR_INCOMPLETE
:
589 vty_out(vty
, "%% Command incomplete: %s\n", line
);
591 case CMD_SUCCESS_DAEMON
: {
593 * FIXME: Don't open pager for exit commands. popen() causes
594 * problems if exited from vtysh at all. This hack shouldn't
595 * cause any problem but is really ugly.
597 if (pager
&& strncmp(line
, "exit", 4))
600 if (!strcmp(cmd
->string
, "configure")) {
601 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
602 cmd_stat
= vtysh_client_execute(
603 &vtysh_client
[i
], line
);
604 if (cmd_stat
== CMD_WARNING
)
610 vline
= cmd_make_strvec(line
);
615 vty_close_pager(vty
);
619 ret
= cmd_execute_command(vline
, vty
, &cmd
, 1);
620 cmd_free_strvec(vline
);
621 if (ret
!= CMD_SUCCESS_DAEMON
)
623 } else if (cmd
->func
) {
624 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
629 cmd_stat
= CMD_SUCCESS
;
630 struct vtysh_client
*vc
;
631 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
632 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
633 if (vtysh_client
[i
].fd
< 0
634 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
635 for (vc
= &vtysh_client
[i
]; vc
;
637 if (vc
->fd
== VTYSH_WAS_ACTIVE
)
640 if (vtysh_client
[i
].fd
< 0
641 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
642 bool any_inst
= false;
643 for (vc
= &vtysh_client
[i
]; vc
;
649 "%s is not running\n",
650 vtysh_client
[i
].name
);
651 cmd_stat
= CMD_ERR_NO_DAEMON
;
655 cmd_stat
= vtysh_client_execute(
656 &vtysh_client
[i
], line
);
657 if (cmd_stat
!= CMD_SUCCESS
)
661 if (cmd_stat
!= CMD_SUCCESS
&& cmd_stat
!= CMD_ERR_NO_DAEMON
)
665 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
669 vty_close_pager(vty
);
674 int vtysh_execute_no_pager(const char *line
)
676 return vtysh_execute_func(line
, 0);
679 int vtysh_execute(const char *line
)
681 return vtysh_execute_func(line
, 1);
684 static char *trim(char *s
)
695 while (end
>= s
&& isspace((unsigned char)*end
))
699 while (*s
&& isspace((unsigned char)*s
))
705 int vtysh_mark_file(const char *filename
)
712 const struct cmd_element
*cmd
;
713 int saved_ret
, prev_node
;
715 char *vty_buf_copy
= NULL
;
716 char *vty_buf_trimmed
= NULL
;
718 if (strncmp("-", filename
, 1) == 0)
721 confp
= fopen(filename
, "r");
724 fprintf(stderr
, "%% Can't open config file %s due to '%s'.\n",
725 filename
, safe_strerror(errno
));
726 return CMD_ERR_NO_FILE
;
730 vty
->wfd
= STDOUT_FILENO
;
731 vty
->type
= VTY_TERM
;
732 vty
->node
= CONFIG_NODE
;
734 vtysh_execute_no_pager("enable");
735 vtysh_execute_no_pager("configure");
736 vty_buf_copy
= XCALLOC(MTYPE_VTYSH_CMD
, VTY_BUFSIZ
);
738 while (fgets(vty
->buf
, VTY_BUFSIZ
, confp
)) {
741 strlcpy(vty_buf_copy
, vty
->buf
, VTY_BUFSIZ
);
742 vty_buf_trimmed
= trim(vty_buf_copy
);
744 if (vty_buf_trimmed
[0] == '!' || vty_buf_trimmed
[0] == '#') {
745 vty_out(vty
, "%s", vty
->buf
);
749 /* Split readline string up into the vector. */
750 vline
= cmd_make_strvec(vty
->buf
);
753 vty_out(vty
, "%s", vty
->buf
);
758 * Ignore the "end" lines, we will generate these where
761 if (strlen(vty_buf_trimmed
) == 3
762 && strncmp("end", vty_buf_trimmed
, 3) == 0) {
763 cmd_free_strvec(vline
);
767 prev_node
= vty
->node
;
768 saved_ret
= ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
771 * If command doesn't succeeded in current node, try to walk up
772 * in node tree. Changing vty->node is enough to try it just
773 * out without actual walkup in the vtysh.
775 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
776 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
777 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
778 && vty
->node
> CONFIG_NODE
) {
779 vty
->node
= node_parent(vty
->node
);
780 ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
785 * If command succeeded in any other node than current (tried >
786 * 0) we have to move into node in the vtysh where it
789 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
790 || ret
== CMD_WARNING
) {
792 vty_out(vty
, "exit\n");
795 * If command didn't succeed in any node, continue with return
796 * value from first try.
800 vty
->node
= prev_node
;
803 cmd_free_strvec(vline
);
806 case CMD_WARNING_CONFIG_FAILED
:
807 if (vty
->type
== VTY_FILE
)
808 fprintf(stderr
, "line %d: Warning...: %s\n",
812 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
814 case CMD_ERR_AMBIGUOUS
:
815 fprintf(stderr
, "line %d: %% Ambiguous command: %s\n",
819 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
820 return CMD_ERR_AMBIGUOUS
;
821 case CMD_ERR_NO_MATCH
:
822 fprintf(stderr
, "line %d: %% Unknown command: %s\n",
826 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
827 return CMD_ERR_NO_MATCH
;
828 case CMD_ERR_INCOMPLETE
:
829 fprintf(stderr
, "line %d: %% Command incomplete: %s\n",
833 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
834 return CMD_ERR_INCOMPLETE
;
836 vty_out(vty
, "%s", vty
->buf
);
837 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
838 vty_out(vty
, "end\n");
840 case CMD_SUCCESS_DAEMON
: {
843 vty_out(vty
, "%s", vty
->buf
);
844 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
845 vty_out(vty
, "end\n");
846 cmd_stat
= vtysh_client_execute(&vtysh_client
[0],
848 if (cmd_stat
!= CMD_SUCCESS
)
852 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
856 /* This is the end */
857 vty_out(vty
, "\nend\n");
859 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
867 /* Configuration make from file. */
868 int vtysh_config_from_file(struct vty
*vty
, FILE *fp
)
871 const struct cmd_element
*cmd
;
873 /* once we have an error, we remember & return that */
874 int retcode
= CMD_SUCCESS
;
875 char *vty_buf_copy
= XCALLOC(MTYPE_VTYSH_CMD
, VTY_BUFSIZ
);
876 char *vty_buf_trimmed
= NULL
;
878 while (fgets(vty
->buf
, VTY_BUFSIZ
, fp
)) {
881 strlcpy(vty_buf_copy
, vty
->buf
, VTY_BUFSIZ
);
882 vty_buf_trimmed
= trim(vty_buf_copy
);
885 * Ignore the "end" lines, we will generate these where
886 * appropriate, otherwise we never execute
887 * XFRR_end_configuration, and start/end markers do not work.
889 if (strmatch(vty_buf_trimmed
, "end"))
892 ret
= command_config_read_one_line(vty
, &cmd
, lineno
, 1);
896 case CMD_WARNING_CONFIG_FAILED
:
897 if (vty
->type
== VTY_FILE
)
898 fprintf(stderr
, "line %d: Warning[%d]...: %s\n",
899 lineno
, vty
->node
, vty
->buf
);
903 case CMD_ERR_AMBIGUOUS
:
905 "line %d: %% Ambiguous command[%d]: %s\n",
906 lineno
, vty
->node
, vty
->buf
);
907 retcode
= CMD_ERR_AMBIGUOUS
;
909 case CMD_ERR_NO_MATCH
:
910 fprintf(stderr
, "line %d: %% Unknown command[%d]: %s",
911 lineno
, vty
->node
, vty
->buf
);
912 retcode
= CMD_ERR_NO_MATCH
;
914 case CMD_ERR_INCOMPLETE
:
916 "line %d: %% Command incomplete[%d]: %s\n",
917 lineno
, vty
->node
, vty
->buf
);
918 retcode
= CMD_ERR_INCOMPLETE
;
920 case CMD_SUCCESS_DAEMON
: {
922 int cmd_stat
= CMD_SUCCESS
;
924 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
925 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
926 cmd_stat
= vtysh_client_execute(
927 &vtysh_client
[i
], vty
->buf
);
929 * CMD_WARNING - Can mean that the
930 * command was parsed successfully but
931 * it was already entered in a few
932 * spots. As such if we receive a
933 * CMD_WARNING from a daemon we
934 * shouldn't stop talking to the other
935 * daemons for the particular command.
937 if (cmd_stat
!= CMD_SUCCESS
938 && cmd_stat
!= CMD_WARNING
) {
940 "line %d: Failure to communicate[%d] to %s, line: %s\n",
942 vtysh_client
[i
].name
,
949 if (cmd_stat
!= CMD_SUCCESS
)
953 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
958 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
964 * Function processes cli commands terminated with '?' character when entered
965 * through either 'vtysh' or 'vtysh -c' interfaces.
967 static int vtysh_process_questionmark(const char *input
, int input_len
)
971 vector vline
, describe
;
972 struct cmd_token
*token
;
977 vline
= cmd_make_strvec(input
);
979 /* In case of '> ?'. */
981 vline
= vector_init(1);
982 vector_set(vline
, NULL
);
983 } else if (input_len
&& isspace((unsigned char)input
[input_len
- 1]))
984 vector_set(vline
, NULL
);
986 describe
= cmd_describe_command(vline
, vty
, &ret
);
988 /* Ambiguous and no match error. */
990 case CMD_ERR_AMBIGUOUS
:
991 cmd_free_strvec(vline
);
992 vector_free(describe
);
993 vty_out(vty
, "%% Ambiguous command.\n");
996 case CMD_ERR_NO_MATCH
:
997 cmd_free_strvec(vline
);
999 vector_free(describe
);
1000 vty_out(vty
, "%% There is no matched command.\n");
1005 /* Get width of command string. */
1007 for (i
= 0; i
< vector_active(describe
); i
++)
1008 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1009 if (token
->text
[0] == '\0')
1012 int len
= strlen(token
->text
);
1018 for (i
= 0; i
< vector_active(describe
); i
++)
1019 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1021 vty_out(vty
, " %-s\n", token
->text
);
1023 vty_out(vty
, " %-*s %s\n", width
, token
->text
,
1026 if (IS_VARYING_TOKEN(token
->type
)) {
1027 const char *ref
= vector_slot(
1028 vline
, vector_active(vline
) - 1);
1030 vector varcomps
= vector_init(VECTOR_MIN_SIZE
);
1031 cmd_variable_complete(token
, ref
, varcomps
);
1033 if (vector_active(varcomps
) > 0) {
1035 rl_get_screen_size(&rows
, &cols
);
1037 char *ac
= cmd_variable_comp2str(
1039 vty_out(vty
, "%s\n", ac
);
1040 XFREE(MTYPE_TMP
, ac
);
1043 vector_free(varcomps
);
1047 cmd_free_strvec(vline
);
1048 vector_free(describe
);
1054 * Entry point for user commands terminated with '?' character and typed through
1055 * the usual vtysh's stdin interface. This is the function being registered with
1058 static int vtysh_rl_describe(int a
, int b
)
1064 ret
= vtysh_process_questionmark(rl_line_buffer
, rl_end
);
1071 * Function in charged of processing vtysh instructions terminating with '?'
1072 * character and received through the 'vtysh -c' interface. If user's
1073 * instruction is well-formatted, we will call the same processing routine
1074 * utilized by the traditional vtysh's stdin interface.
1076 int vtysh_execute_command_questionmark(char *input
)
1078 int input_len
, qmark_count
= 0;
1081 if (!(input
&& *input
))
1084 /* Finding out question_mark count and strlen */
1085 for (str
= input
; *str
; ++str
) {
1089 input_len
= str
- input
;
1092 * Verify that user's input terminates in '?' and that patterns such as
1093 * 'cmd ? subcmd ?' are prevented.
1095 if (qmark_count
!= 1 || input
[input_len
- 1] != '?')
1099 * Questionmark-processing function is not expecting to receive '?'
1100 * character in input string.
1102 input
[input_len
- 1] = '\0';
1104 return vtysh_process_questionmark(input
, input_len
- 1);
1107 /* Result of cmd_complete_command() call will be stored here
1108 * and used in new_completion() in order to put the space in
1109 * correct places only. */
1110 int complete_status
;
1112 static char *command_generator(const char *text
, int state
)
1115 static char **matched
= NULL
;
1116 static int index
= 0;
1122 if (vty
->node
== AUTH_NODE
|| vty
->node
== AUTH_ENABLE_NODE
)
1125 vline
= cmd_make_strvec(rl_line_buffer
);
1130 isspace((unsigned char)rl_line_buffer
[rl_end
- 1]))
1131 vector_set(vline
, NULL
);
1133 matched
= cmd_complete_command(vline
, vty
, &complete_status
);
1134 cmd_free_strvec(vline
);
1137 if (matched
&& matched
[index
]) {
1138 XCOUNTFREE(MTYPE_COMPLETION
, matched
[index
]);
1139 return matched
[index
++];
1142 XFREE(MTYPE_TMP
, matched
);
1147 static char **new_completion(const char *text
, int start
, int end
)
1151 matches
= rl_completion_matches(text
, command_generator
);
1155 if (complete_status
!= CMD_COMPLETE_FULL_MATCH
)
1156 /* only append a space on full match */
1157 rl_completion_append_character
= '\0';
1163 /* Vty node structures. */
1165 static struct cmd_node bgp_node
= {
1168 .parent_node
= CONFIG_NODE
,
1169 .prompt
= "%s(config-router)# ",
1171 #endif /* HAVE_BGPD */
1173 static struct cmd_node rip_node
= {
1176 .parent_node
= CONFIG_NODE
,
1177 .prompt
= "%s(config-router)# ",
1181 static struct cmd_node isis_node
= {
1184 .parent_node
= CONFIG_NODE
,
1185 .prompt
= "%s(config-router)# ",
1187 #endif /* HAVE_ISISD */
1190 static struct cmd_node openfabric_node
= {
1191 .name
= "openfabric",
1192 .node
= OPENFABRIC_NODE
,
1193 .parent_node
= CONFIG_NODE
,
1194 .prompt
= "%s(config-router)# ",
1196 #endif /* HAVE_FABRICD */
1198 static struct cmd_node interface_node
= {
1199 .name
= "interface",
1200 .node
= INTERFACE_NODE
,
1201 .parent_node
= CONFIG_NODE
,
1202 .prompt
= "%s(config-if)# ",
1205 static struct cmd_node pw_node
= {
1208 .parent_node
= CONFIG_NODE
,
1209 .prompt
= "%s(config-pw)# ",
1212 static struct cmd_node segment_routing_node
= {
1213 .name
= "segment-routing",
1214 .node
= SEGMENT_ROUTING_NODE
,
1215 .parent_node
= CONFIG_NODE
,
1216 .prompt
= "%s(config-sr)# ",
1219 #if defined(HAVE_PATHD)
1220 static struct cmd_node sr_traffic_eng_node
= {
1221 .name
= "sr traffic-eng",
1222 .node
= SR_TRAFFIC_ENG_NODE
,
1223 .parent_node
= SEGMENT_ROUTING_NODE
,
1224 .prompt
= "%s(config-sr-te)# ",
1227 static struct cmd_node srte_segment_list_node
= {
1228 .name
= "srte segment-list",
1229 .node
= SR_SEGMENT_LIST_NODE
,
1230 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1231 .prompt
= "%s(config-sr-te-segment-list)# ",
1234 static struct cmd_node srte_policy_node
= {
1235 .name
= "srte policy",
1236 .node
= SR_POLICY_NODE
,
1237 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1238 .prompt
= "%s(config-sr-te-policy)# ",
1241 static struct cmd_node srte_candidate_dyn_node
= {
1242 .name
= "srte candidate-dyn",
1243 .node
= SR_CANDIDATE_DYN_NODE
,
1244 .parent_node
= SR_POLICY_NODE
,
1245 .prompt
= "%s(config-sr-te-candidate)# ",
1248 static struct cmd_node pcep_node
= {
1249 .name
= "srte pcep",
1251 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1252 .prompt
= "%s(config-sr-te-pcep)# "
1255 static struct cmd_node pcep_pcc_node
= {
1256 .name
= "srte pcep pcc",
1257 .node
= PCEP_PCC_NODE
,
1258 .parent_node
= PCEP_NODE
,
1259 .prompt
= "%s(config-sr-te-pcep-pcc)# ",
1262 static struct cmd_node pcep_pce_node
= {
1263 .name
= "srte pcep pce-peer",
1264 .node
= PCEP_PCE_NODE
,
1265 .parent_node
= PCEP_NODE
,
1266 .prompt
= "%s(config-sr-te-pcep-pce-peer)# ",
1269 static struct cmd_node pcep_pce_config_node
= {
1270 .name
= "srte pcep pce-config",
1271 .node
= PCEP_PCE_CONFIG_NODE
,
1272 .parent_node
= PCEP_NODE
,
1273 .prompt
= "%s(pcep-sr-te-pcep-pce-config)# ",
1275 #endif /* HAVE_PATHD */
1277 static struct cmd_node vrf_node
= {
1280 .parent_node
= CONFIG_NODE
,
1281 .prompt
= "%s(config-vrf)# ",
1284 static struct cmd_node nh_group_node
= {
1285 .name
= "nexthop-group",
1286 .node
= NH_GROUP_NODE
,
1287 .parent_node
= CONFIG_NODE
,
1288 .prompt
= "%s(config-nh-group)# ",
1291 static struct cmd_node rmap_node
= {
1294 .parent_node
= CONFIG_NODE
,
1295 .prompt
= "%s(config-route-map)# ",
1298 static struct cmd_node srv6_node
= {
1301 .parent_node
= SEGMENT_ROUTING_NODE
,
1302 .prompt
= "%s(config-srv6)# ",
1305 static struct cmd_node srv6_locs_node
= {
1306 .name
= "srv6-locators",
1307 .node
= SRV6_LOCS_NODE
,
1308 .parent_node
= SRV6_NODE
,
1309 .prompt
= "%s(config-srv6-locators)# ",
1312 static struct cmd_node srv6_loc_node
= {
1313 .name
= "srv6-locator",
1314 .node
= SRV6_LOC_NODE
,
1315 .parent_node
= SRV6_LOCS_NODE
,
1316 .prompt
= "%s(config-srv6-locator)# ",
1320 static struct cmd_node pbr_map_node
= {
1322 .node
= PBRMAP_NODE
,
1323 .parent_node
= CONFIG_NODE
,
1324 .prompt
= "%s(config-pbr-map)# ",
1326 #endif /* HAVE_PBRD */
1328 static struct cmd_node zebra_node
= {
1331 .parent_node
= CONFIG_NODE
,
1332 .prompt
= "%s(config-router)# ",
1336 static struct cmd_node bgp_vpnv4_node
= {
1337 .name
= "bgp vpnv4",
1338 .node
= BGP_VPNV4_NODE
,
1339 .parent_node
= BGP_NODE
,
1340 .prompt
= "%s(config-router-af)# ",
1344 static struct cmd_node bgp_vpnv6_node
= {
1345 .name
= "bgp vpnv6",
1346 .node
= BGP_VPNV6_NODE
,
1347 .parent_node
= BGP_NODE
,
1348 .prompt
= "%s(config-router-af)# ",
1352 static struct cmd_node bgp_flowspecv4_node
= {
1353 .name
= "bgp ipv4 flowspec",
1354 .node
= BGP_FLOWSPECV4_NODE
,
1355 .parent_node
= BGP_NODE
,
1356 .prompt
= "%s(config-router-af)# ",
1360 static struct cmd_node bgp_flowspecv6_node
= {
1361 .name
= "bgp ipv6 flowspec",
1362 .node
= BGP_FLOWSPECV6_NODE
,
1363 .parent_node
= BGP_NODE
,
1364 .prompt
= "%s(config-router-af)# ",
1368 static struct cmd_node bgp_ipv4_node
= {
1369 .name
= "bgp ipv4 unicast",
1370 .node
= BGP_IPV4_NODE
,
1371 .parent_node
= BGP_NODE
,
1372 .prompt
= "%s(config-router-af)# ",
1376 static struct cmd_node bgp_ipv4m_node
= {
1377 .name
= "bgp ipv4 multicast",
1378 .node
= BGP_IPV4M_NODE
,
1379 .parent_node
= BGP_NODE
,
1380 .prompt
= "%s(config-router-af)# ",
1384 static struct cmd_node bgp_ipv4l_node
= {
1385 .name
= "bgp ipv4 labeled unicast",
1386 .node
= BGP_IPV4L_NODE
,
1387 .parent_node
= BGP_NODE
,
1388 .prompt
= "%s(config-router-af)# ",
1392 static struct cmd_node bgp_ipv6_node
= {
1394 .node
= BGP_IPV6_NODE
,
1395 .parent_node
= BGP_NODE
,
1396 .prompt
= "%s(config-router-af)# ",
1400 static struct cmd_node bgp_ipv6m_node
= {
1401 .name
= "bgp ipv6 multicast",
1402 .node
= BGP_IPV6M_NODE
,
1403 .parent_node
= BGP_NODE
,
1404 .prompt
= "%s(config-router-af)# ",
1408 static struct cmd_node bgp_evpn_node
= {
1410 .node
= BGP_EVPN_NODE
,
1411 .parent_node
= BGP_NODE
,
1412 .prompt
= "%s(config-router-af)# ",
1416 static struct cmd_node bgp_evpn_vni_node
= {
1417 .name
= "bgp evpn vni",
1418 .node
= BGP_EVPN_VNI_NODE
,
1419 .parent_node
= BGP_EVPN_NODE
,
1420 .prompt
= "%s(config-router-af-vni)# ",
1423 static struct cmd_node bgp_ipv6l_node
= {
1424 .name
= "bgp ipv6 labeled unicast",
1425 .node
= BGP_IPV6L_NODE
,
1426 .parent_node
= BGP_NODE
,
1427 .prompt
= "%s(config-router-af)# ",
1431 #ifdef ENABLE_BGP_VNC
1432 static struct cmd_node bgp_vnc_defaults_node
= {
1433 .name
= "bgp vnc defaults",
1434 .node
= BGP_VNC_DEFAULTS_NODE
,
1435 .parent_node
= BGP_NODE
,
1436 .prompt
= "%s(config-router-vnc-defaults)# ",
1439 static struct cmd_node bgp_vnc_nve_group_node
= {
1440 .name
= "bgp vnc nve",
1441 .node
= BGP_VNC_NVE_GROUP_NODE
,
1442 .parent_node
= BGP_NODE
,
1443 .prompt
= "%s(config-router-vnc-nve-group)# ",
1446 static struct cmd_node bgp_vrf_policy_node
= {
1447 .name
= "bgp vrf policy",
1448 .node
= BGP_VRF_POLICY_NODE
,
1449 .parent_node
= BGP_NODE
,
1450 .prompt
= "%s(config-router-vrf-policy)# ",
1453 static struct cmd_node bgp_vnc_l2_group_node
= {
1454 .name
= "bgp vnc l2",
1455 .node
= BGP_VNC_L2_GROUP_NODE
,
1456 .parent_node
= BGP_NODE
,
1457 .prompt
= "%s(config-router-vnc-l2-group)# ",
1459 #endif /* ENABLE_BGP_VNC */
1461 static struct cmd_node bmp_node
= {
1464 .parent_node
= BGP_NODE
,
1465 .prompt
= "%s(config-bgp-bmp)# "
1468 static struct cmd_node bgp_srv6_node
= {
1470 .node
= BGP_SRV6_NODE
,
1471 .parent_node
= BGP_NODE
,
1472 .prompt
= "%s(config-router-srv6)# ",
1474 #endif /* HAVE_BGPD */
1477 static struct cmd_node ospf_node
= {
1480 .parent_node
= CONFIG_NODE
,
1481 .prompt
= "%s(config-router)# ",
1483 #endif /* HAVE_OSPFD */
1486 static struct cmd_node eigrp_node
= {
1489 .parent_node
= CONFIG_NODE
,
1490 .prompt
= "%s(config-router)# ",
1492 #endif /* HAVE_EIGRPD */
1495 static struct cmd_node babel_node
= {
1498 .parent_node
= CONFIG_NODE
,
1499 .prompt
= "%s(config-router)# ",
1501 #endif /* HAVE_BABELD */
1503 static struct cmd_node ripng_node
= {
1506 .parent_node
= CONFIG_NODE
,
1507 .prompt
= "%s(config-router)# ",
1511 static struct cmd_node ospf6_node
= {
1514 .parent_node
= CONFIG_NODE
,
1515 .prompt
= "%s(config-ospf6)# ",
1517 #endif /* HAVE_OSPF6D */
1520 static struct cmd_node ldp_node
= {
1523 .parent_node
= CONFIG_NODE
,
1524 .prompt
= "%s(config-ldp)# ",
1527 static struct cmd_node ldp_ipv4_node
= {
1529 .node
= LDP_IPV4_NODE
,
1530 .parent_node
= LDP_NODE
,
1531 .prompt
= "%s(config-ldp-af)# ",
1534 static struct cmd_node ldp_ipv6_node
= {
1536 .node
= LDP_IPV6_NODE
,
1537 .parent_node
= LDP_NODE
,
1538 .prompt
= "%s(config-ldp-af)# ",
1541 static struct cmd_node ldp_ipv4_iface_node
= {
1542 .name
= "ldp ipv4 interface",
1543 .node
= LDP_IPV4_IFACE_NODE
,
1544 .parent_node
= LDP_IPV4_NODE
,
1545 .prompt
= "%s(config-ldp-af-if)# ",
1548 static struct cmd_node ldp_ipv6_iface_node
= {
1549 .name
= "ldp ipv6 interface",
1550 .node
= LDP_IPV6_IFACE_NODE
,
1551 .parent_node
= LDP_IPV6_NODE
,
1552 .prompt
= "%s(config-ldp-af-if)# ",
1555 static struct cmd_node ldp_l2vpn_node
= {
1556 .name
= "ldp l2vpn",
1557 .node
= LDP_L2VPN_NODE
,
1558 .parent_node
= CONFIG_NODE
,
1559 .prompt
= "%s(config-l2vpn)# ",
1562 static struct cmd_node ldp_pseudowire_node
= {
1564 .node
= LDP_PSEUDOWIRE_NODE
,
1565 .parent_node
= LDP_L2VPN_NODE
,
1566 .prompt
= "%s(config-l2vpn-pw)# ",
1568 #endif /* HAVE_LDPD */
1570 static struct cmd_node keychain_node
= {
1572 .node
= KEYCHAIN_NODE
,
1573 .parent_node
= CONFIG_NODE
,
1574 .prompt
= "%s(config-keychain)# ",
1577 static struct cmd_node keychain_key_node
= {
1578 .name
= "keychain key",
1579 .node
= KEYCHAIN_KEY_NODE
,
1580 .parent_node
= KEYCHAIN_NODE
,
1581 .prompt
= "%s(config-keychain-key)# ",
1584 struct cmd_node link_params_node
= {
1585 .name
= "link-params",
1586 .node
= LINK_PARAMS_NODE
,
1587 .parent_node
= INTERFACE_NODE
,
1588 .prompt
= "%s(config-link-params)# ",
1593 static struct cmd_node rpki_node
= {
1596 .parent_node
= CONFIG_NODE
,
1597 .prompt
= "%s(config-rpki)# ",
1599 #endif /* HAVE_BGPD */
1602 static struct cmd_node bfd_node
= {
1605 .parent_node
= CONFIG_NODE
,
1606 .prompt
= "%s(config-bfd)# ",
1609 static struct cmd_node bfd_peer_node
= {
1611 .node
= BFD_PEER_NODE
,
1612 .parent_node
= BFD_NODE
,
1613 .prompt
= "%s(config-bfd-peer)# ",
1616 static struct cmd_node bfd_profile_node
= {
1617 .name
= "bfd profile",
1618 .node
= BFD_PROFILE_NODE
,
1619 .parent_node
= BFD_NODE
,
1620 .prompt
= "%s(config-bfd-profile)# ",
1622 #endif /* HAVE_BFDD */
1624 /* Defined in lib/vty.c */
1625 extern struct cmd_node vty_node
;
1627 /* When '^Z' is received from vty, move down to the enable mode. */
1628 static int vtysh_end(void)
1630 switch (vty
->node
) {
1633 /* Nothing to do. */
1636 vty
->node
= ENABLE_NODE
;
1642 #include "vtysh/vtysh_clippy.c"
1644 DEFUNSH(VTYSH_REALLYALL
, vtysh_end_all
, vtysh_end_all_cmd
, "end",
1645 "End current mode and change to enable mode\n")
1650 DEFUNSH(VTYSH_ZEBRA
, srv6
, srv6_cmd
,
1652 "Segment-Routing SRv6 configuration\n")
1654 vty
->node
= SRV6_NODE
;
1658 DEFUNSH(VTYSH_ZEBRA
, srv6_locators
, srv6_locators_cmd
,
1660 "Segment-Routing SRv6 locators configuration\n")
1662 vty
->node
= SRV6_LOCS_NODE
;
1666 DEFUNSH(VTYSH_ZEBRA
, srv6_locator
, srv6_locator_cmd
,
1668 "Segment Routing SRv6 locator\n"
1669 "Specify locator-name\n")
1671 vty
->node
= SRV6_LOC_NODE
;
1676 DEFUNSH(VTYSH_BGPD
, router_bgp
, router_bgp_cmd
,
1677 "router bgp [ASNUM [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]",
1678 ROUTER_STR BGP_STR AS_STR
1679 "BGP view\nBGP VRF\n"
1681 "Force the AS notation output\n"
1682 "use 'AA.BB' format for AS 4 byte values\n"
1683 "use 'AA.BB' format for all AS values\n"
1684 "use plain format for all AS values\n")
1686 vty
->node
= BGP_NODE
;
1690 #ifdef KEEP_OLD_VPN_COMMANDS
1691 DEFUNSH(VTYSH_BGPD
, address_family_vpnv4
, address_family_vpnv4_cmd
,
1692 "address-family vpnv4 [unicast]",
1693 "Enter Address Family command mode\n"
1695 BGP_AF_MODIFIER_STR
)
1697 vty
->node
= BGP_VPNV4_NODE
;
1701 DEFUNSH(VTYSH_BGPD
, address_family_vpnv6
, address_family_vpnv6_cmd
,
1702 "address-family vpnv6 [unicast]",
1703 "Enter Address Family command mode\n"
1705 BGP_AF_MODIFIER_STR
)
1707 vty
->node
= BGP_VPNV6_NODE
;
1710 #endif /* KEEP_OLD_VPN_COMMANDS */
1712 DEFUNSH(VTYSH_BGPD
, address_family_ipv4
, address_family_ipv4_cmd
,
1713 "address-family ipv4 [unicast]",
1714 "Enter Address Family command mode\n"
1716 BGP_AF_MODIFIER_STR
)
1718 vty
->node
= BGP_IPV4_NODE
;
1722 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv4
, address_family_flowspecv4_cmd
,
1723 "address-family ipv4 flowspec",
1724 "Enter Address Family command mode\n"
1726 BGP_AF_MODIFIER_STR
)
1728 vty
->node
= BGP_FLOWSPECV4_NODE
;
1732 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv6
, address_family_flowspecv6_cmd
,
1733 "address-family ipv6 flowspec",
1734 "Enter Address Family command mode\n"
1736 BGP_AF_MODIFIER_STR
)
1738 vty
->node
= BGP_FLOWSPECV6_NODE
;
1742 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_multicast
,
1743 address_family_ipv4_multicast_cmd
, "address-family ipv4 multicast",
1744 "Enter Address Family command mode\n"
1746 BGP_AF_MODIFIER_STR
)
1748 vty
->node
= BGP_IPV4M_NODE
;
1752 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_vpn
, address_family_ipv4_vpn_cmd
,
1753 "address-family ipv4 vpn",
1754 "Enter Address Family command mode\n"
1756 BGP_AF_MODIFIER_STR
)
1758 vty
->node
= BGP_VPNV4_NODE
;
1762 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_labeled_unicast
,
1763 address_family_ipv4_labeled_unicast_cmd
,
1764 "address-family ipv4 labeled-unicast",
1765 "Enter Address Family command mode\n"
1767 BGP_AF_MODIFIER_STR
)
1769 vty
->node
= BGP_IPV4L_NODE
;
1773 DEFUNSH(VTYSH_BGPD
, address_family_ipv6
, address_family_ipv6_cmd
,
1774 "address-family ipv6 [unicast]",
1775 "Enter Address Family command mode\n"
1777 BGP_AF_MODIFIER_STR
)
1779 vty
->node
= BGP_IPV6_NODE
;
1783 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_multicast
,
1784 address_family_ipv6_multicast_cmd
, "address-family ipv6 multicast",
1785 "Enter Address Family command mode\n"
1787 BGP_AF_MODIFIER_STR
)
1789 vty
->node
= BGP_IPV6M_NODE
;
1793 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_vpn
, address_family_ipv6_vpn_cmd
,
1794 "address-family ipv6 vpn",
1795 "Enter Address Family command mode\n"
1797 BGP_AF_MODIFIER_STR
)
1799 vty
->node
= BGP_VPNV6_NODE
;
1803 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_labeled_unicast
,
1804 address_family_ipv6_labeled_unicast_cmd
,
1805 "address-family ipv6 labeled-unicast",
1806 "Enter Address Family command mode\n"
1808 BGP_AF_MODIFIER_STR
)
1810 vty
->node
= BGP_IPV6L_NODE
;
1818 "Enable rpki and enter rpki configuration mode\n")
1820 vty
->node
= RPKI_NODE
;
1827 "bmp targets BMPTARGETS",
1828 "BGP Monitoring Protocol\n"
1829 "Create BMP target group\n"
1830 "Name of the BMP target group\n")
1832 vty
->node
= BMP_NODE
;
1839 "segment-routing srv6",
1840 "Segment-Routing configuration\n"
1841 "Segment-Routing SRv6 configuration\n")
1843 vty
->node
= BGP_SRV6_NODE
;
1851 "exit Segment-Routing SRv6 configuration\n")
1853 if (vty
->node
== BGP_SRV6_NODE
)
1854 vty
->node
= BGP_NODE
;
1862 "quit Segment-Routing SRv6 configuration\n")
1864 if (vty
->node
== BGP_SRV6_NODE
)
1865 vty
->node
= BGP_NODE
;
1869 DEFUNSH(VTYSH_BGPD
, address_family_evpn
, address_family_evpn_cmd
,
1870 "address-family <l2vpn evpn>",
1871 "Enter Address Family command mode\n"
1873 BGP_AF_MODIFIER_STR
)
1875 vty
->node
= BGP_EVPN_NODE
;
1879 DEFUNSH(VTYSH_BGPD
, bgp_evpn_vni
, bgp_evpn_vni_cmd
, "vni " CMD_VNI_RANGE
,
1880 "VXLAN Network Identifier\n"
1883 vty
->node
= BGP_EVPN_VNI_NODE
;
1887 #if defined(ENABLE_BGP_VNC)
1888 DEFUNSH(VTYSH_BGPD
, vnc_defaults
, vnc_defaults_cmd
, "vnc defaults",
1889 "VNC/RFP related configuration\n"
1890 "Configure default NVE group\n")
1892 vty
->node
= BGP_VNC_DEFAULTS_NODE
;
1896 DEFUNSH(VTYSH_BGPD
, vnc_nve_group
, vnc_nve_group_cmd
, "vnc nve-group NAME",
1897 "VNC/RFP related configuration\n"
1898 "Configure a NVE group\n"
1901 vty
->node
= BGP_VNC_NVE_GROUP_NODE
;
1905 DEFUNSH(VTYSH_BGPD
, vnc_vrf_policy
, vnc_vrf_policy_cmd
, "vrf-policy NAME",
1906 "Configure a VRF policy group\n"
1909 vty
->node
= BGP_VRF_POLICY_NODE
;
1913 DEFUNSH(VTYSH_BGPD
, vnc_l2_group
, vnc_l2_group_cmd
, "vnc l2-group NAME",
1914 "VNC/RFP related configuration\n"
1915 "Configure a L2 group\n"
1918 vty
->node
= BGP_VNC_L2_GROUP_NODE
;
1922 DEFUNSH(VTYSH_BGPD
, exit_vnc_config
, exit_vnc_config_cmd
, "exit-vnc",
1923 "Exit from VNC configuration mode\n")
1925 if (vty
->node
== BGP_VNC_DEFAULTS_NODE
1926 || vty
->node
== BGP_VNC_NVE_GROUP_NODE
1927 || vty
->node
== BGP_VNC_L2_GROUP_NODE
)
1928 vty
->node
= BGP_NODE
;
1932 DEFUNSH(VTYSH_BGPD
, exit_vrf_policy
, exit_vrf_policy_cmd
, "exit-vrf-policy",
1933 "Exit from VRF policy configuration mode\n")
1935 if (vty
->node
== BGP_VRF_POLICY_NODE
)
1936 vty
->node
= BGP_NODE
;
1940 #endif /* HAVE_BGPD */
1942 DEFUNSH(VTYSH_KEYS
, key_chain
, key_chain_cmd
, "key chain WORD",
1943 "Authentication key management\n"
1944 "Key-chain management\n"
1947 vty
->node
= KEYCHAIN_NODE
;
1951 DEFUNSH(VTYSH_KEYS
, key
, key_cmd
, "key (0-2147483647)",
1953 "Key identifier number\n")
1955 vty
->node
= KEYCHAIN_KEY_NODE
;
1960 DEFUNSH(VTYSH_RIPD
, router_rip
, router_rip_cmd
, "router rip [vrf NAME]",
1961 ROUTER_STR
"RIP\n" VRF_CMD_HELP_STR
)
1963 vty
->node
= RIP_NODE
;
1966 #endif /* HAVE_RIPD */
1969 DEFUNSH(VTYSH_RIPNGD
, router_ripng
, router_ripng_cmd
, "router ripng [vrf NAME]",
1970 ROUTER_STR
"RIPng\n" VRF_CMD_HELP_STR
)
1972 vty
->node
= RIPNG_NODE
;
1975 #endif /* HAVE_RIPNGD */
1978 DEFUNSH(VTYSH_OSPFD
, router_ospf
, router_ospf_cmd
,
1979 "router ospf [(1-65535)] [vrf NAME]",
1980 "Enable a routing process\n"
1981 "Start OSPF configuration\n"
1985 vty
->node
= OSPF_NODE
;
1988 #endif /* HAVE_OSPFD */
1991 DEFUNSH(VTYSH_EIGRPD
, router_eigrp
, router_eigrp_cmd
, "router eigrp (1-65535) [vrf NAME]",
1992 "Enable a routing process\n"
1993 "Start EIGRP configuration\n"
1994 "AS number to use\n"
1997 vty
->node
= EIGRP_NODE
;
2000 #endif /* HAVE_EIGRPD */
2003 DEFUNSH(VTYSH_BABELD
, router_babel
, router_babel_cmd
, "router babel",
2004 "Enable a routing process\n"
2005 "Make Babel instance command\n")
2007 vty
->node
= BABEL_NODE
;
2010 #endif /* HAVE_BABELD */
2013 DEFUNSH(VTYSH_OSPF6D
, router_ospf6
, router_ospf6_cmd
, "router ospf6 [vrf NAME]",
2014 ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR
)
2016 vty
->node
= OSPF6_NODE
;
2021 #if defined(HAVE_LDPD)
2022 DEFUNSH(VTYSH_LDPD
, ldp_mpls_ldp
, ldp_mpls_ldp_cmd
, "mpls ldp",
2023 "Global MPLS configuration subcommands\n"
2024 "Label Distribution Protocol\n")
2026 vty
->node
= LDP_NODE
;
2030 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv4
, ldp_address_family_ipv4_cmd
,
2031 "address-family ipv4",
2032 "Configure Address Family and its parameters\n"
2035 vty
->node
= LDP_IPV4_NODE
;
2039 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv6
, ldp_address_family_ipv6_cmd
,
2040 "address-family ipv6",
2041 "Configure Address Family and its parameters\n"
2044 vty
->node
= LDP_IPV6_NODE
;
2048 DEFUNSH(VTYSH_LDPD
, ldp_exit_address_family
, ldp_exit_address_family_cmd
,
2049 "exit-address-family", "Exit from Address Family configuration mode\n")
2051 if (vty
->node
== LDP_IPV4_NODE
|| vty
->node
== LDP_IPV6_NODE
)
2052 vty
->node
= LDP_NODE
;
2056 DEFUNSH(VTYSH_LDPD
, ldp_interface_ifname
, ldp_interface_ifname_cmd
,
2058 "Enable LDP on an interface and enter interface submode\n"
2059 "Interface's name\n")
2061 switch (vty
->node
) {
2063 vty
->node
= LDP_IPV4_IFACE_NODE
;
2066 vty
->node
= LDP_IPV6_IFACE_NODE
;
2075 DEFUNSH(VTYSH_LDPD
, ldp_l2vpn_word_type_vpls
, ldp_l2vpn_word_type_vpls_cmd
,
2076 "l2vpn WORD type vpls",
2077 "Configure l2vpn commands\n"
2080 "Virtual Private LAN Service\n")
2082 vty
->node
= LDP_L2VPN_NODE
;
2086 DEFUNSH(VTYSH_LDPD
, ldp_member_pseudowire_ifname
,
2087 ldp_member_pseudowire_ifname_cmd
, "member pseudowire IFNAME",
2088 "L2VPN member configuration\n"
2089 "Pseudowire interface\n"
2090 "Interface's name\n")
2092 vty
->node
= LDP_PSEUDOWIRE_NODE
;
2098 DEFUNSH(VTYSH_ISISD
, router_isis
, router_isis_cmd
,
2099 "router isis WORD [vrf NAME]",
2102 "ISO Routing area tag\n" VRF_CMD_HELP_STR
)
2104 vty
->node
= ISIS_NODE
;
2107 #endif /* HAVE_ISISD */
2110 DEFUNSH(VTYSH_FABRICD
, router_openfabric
, router_openfabric_cmd
, "router openfabric WORD",
2112 "OpenFabric routing protocol\n"
2113 "ISO Routing area tag\n")
2115 vty
->node
= OPENFABRIC_NODE
;
2118 #endif /* HAVE_FABRICD */
2120 DEFUNSH(VTYSH_SR
, segment_routing
, segment_routing_cmd
,
2122 "Configure segment routing\n")
2124 vty
->node
= SEGMENT_ROUTING_NODE
;
2128 #if defined (HAVE_PATHD)
2129 DEFUNSH(VTYSH_PATHD
, sr_traffic_eng
, sr_traffic_eng_cmd
,
2131 "Configure SR traffic engineering\n")
2133 vty
->node
= SR_TRAFFIC_ENG_NODE
;
2137 DEFUNSH(VTYSH_PATHD
, srte_segment_list
, srte_segment_list_cmd
,
2138 "segment-list WORD$name",
2140 "Segment List Name\n")
2142 vty
->node
= SR_SEGMENT_LIST_NODE
;
2146 DEFUNSH(VTYSH_PATHD
, srte_policy
, srte_policy_cmd
,
2147 "policy color (0-4294967295) endpoint <A.B.C.D|X:X::X:X>",
2148 "Segment Routing Policy\n"
2150 "SR Policy color value\n"
2151 "SR Policy endpoint\n"
2152 "SR Policy endpoint IPv4 address\n"
2153 "SR Policy endpoint IPv6 address\n")
2155 vty
->node
= SR_POLICY_NODE
;
2159 DEFUNSH(VTYSH_PATHD
, srte_policy_candidate_dyn_path
,
2160 srte_policy_candidate_dyn_path_cmd
,
2161 "candidate-path preference (0-4294967295) name WORD dynamic",
2162 "Segment Routing Policy Candidate Path\n"
2163 "Segment Routing Policy Candidate Path Preference\n"
2164 "Administrative Preference\n"
2165 "Segment Routing Policy Candidate Path Name\n"
2169 vty
->node
= SR_CANDIDATE_DYN_NODE
;
2173 DEFUNSH(VTYSH_PATHD
, pcep
, pcep_cmd
,
2175 "Configure SR pcep\n")
2177 vty
->node
= PCEP_NODE
;
2181 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcc
, pcep_cli_pcc_cmd
,
2183 "PCC configuration\n")
2185 vty
->node
= PCEP_PCC_NODE
;
2189 DEFUNSH(VTYSH_PATHD
, pcep_cli_pce
, pcep_cli_pce_cmd
,
2191 "PCE configuration\n"
2194 vty
->node
= PCEP_PCE_NODE
;
2198 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcep_pce_config
, pcep_cli_pcep_pce_config_cmd
,
2200 "PCEP peer Configuration Group\n"
2201 "PCEP peer Configuration Group name\n")
2203 vty
->node
= PCEP_PCE_CONFIG_NODE
;
2207 #endif /* HAVE_PATHD */
2209 /* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
2210 DEFUNSH(VTYSH_AFFMAP
, affinity_map
, vtysh_affinity_map_cmd
,
2211 "affinity-map NAME bit-position (0-1023)",
2212 "Affinity map configuration\n"
2213 "Affinity attribute name\n"
2214 "Bit position for affinity attribute value\n"
2220 /* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
2221 DEFUNSH(VTYSH_AFFMAP
, no_affinity_map
, vtysh_no_affinity_map_cmd
,
2222 "no affinity-map NAME$name [bit-position (0-1023)$position]",
2224 "Affinity map configuration\n"
2225 "Affinity attribute name\n"
2226 "Bit position for affinity attribute value\n"
2232 DEFUNSH(VTYSH_RMAP
, vtysh_route_map
, vtysh_route_map_cmd
,
2233 "route-map RMAP_NAME <deny|permit> (1-65535)",
2234 "Create route-map or enter route-map command mode\n"
2236 "Route map denies set operations\n"
2237 "Route map permits set operations\n"
2238 "Sequence to insert to/delete from existing route-map entry\n")
2240 vty
->node
= RMAP_NODE
;
2245 DEFUNSH(VTYSH_PBRD
, vtysh_pbr_map
, vtysh_pbr_map_cmd
,
2246 "pbr-map PBRMAP seq (1-700)",
2247 "Create pbr-map or enter pbr-map command mode\n"
2248 "The name of the PBR MAP\n"
2249 "Sequence to insert to/delete from existing pbr-map entry\n"
2250 "Sequence number\n")
2252 vty
->node
= PBRMAP_NODE
;
2256 DEFSH(VTYSH_PBRD
, vtysh_no_pbr_map_cmd
, "no pbr-map PBRMAP [seq (1-700)]",
2259 "The name of the PBR MAP\n"
2260 "Sequence to delete from existing pbr-map entry\n"
2261 "Sequence number\n")
2262 #endif /* HAVE_PBRD */
2265 DEFUNSH(VTYSH_BFDD
, bfd_enter
, bfd_enter_cmd
, "bfd", "Configure BFD peers\n")
2267 vty
->node
= BFD_NODE
;
2271 DEFUNSH(VTYSH_BFDD
, bfd_peer_enter
, bfd_peer_enter_cmd
,
2272 "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
2274 "IPv4 peer address\n"
2275 "IPv6 peer address\n"
2276 "Configure multihop\n"
2277 "Configure local address\n"
2278 "IPv4 local address\n"
2279 "IPv6 local address\n"
2281 "Configure interface name to use\n"
2283 "Configure VRF name\n")
2285 vty
->node
= BFD_PEER_NODE
;
2289 DEFUNSH(VTYSH_BFDD
, bfd_profile_enter
, bfd_profile_enter_cmd
,
2292 BFD_PROFILE_NAME_STR
)
2294 vty
->node
= BFD_PROFILE_NODE
;
2297 #endif /* HAVE_BFDD */
2299 DEFUNSH(VTYSH_ALL
, vtysh_line_vty
, vtysh_line_vty_cmd
, "line vty",
2300 "Configure a terminal line\n"
2301 "Virtual terminal\n")
2303 vty
->node
= VTY_NODE
;
2307 DEFUNSH(VTYSH_REALLYALL
, vtysh_enable
, vtysh_enable_cmd
, "enable",
2308 "Turn on privileged mode command\n")
2310 vty
->node
= ENABLE_NODE
;
2314 DEFUNSH(VTYSH_REALLYALL
, vtysh_disable
, vtysh_disable_cmd
, "disable",
2315 "Turn off privileged mode command\n")
2317 if (vty
->node
== ENABLE_NODE
)
2318 vty
->node
= VIEW_NODE
;
2322 DEFUNSH(VTYSH_REALLYALL
, vtysh_config_terminal
, vtysh_config_terminal_cmd
,
2323 "configure [terminal]",
2324 "Configuration from vty interface\n"
2325 "Configuration terminal\n")
2327 vty
->node
= CONFIG_NODE
;
2331 static int vtysh_exit(struct vty
*vty
)
2333 struct cmd_node
*cnode
= vector_lookup(cmdvec
, vty
->node
);
2335 if (vty
->node
== VIEW_NODE
|| vty
->node
== ENABLE_NODE
)
2337 if (cnode
->node_exit
)
2338 cnode
->node_exit(vty
);
2339 if (cnode
->parent_node
)
2340 vty
->node
= cnode
->parent_node
;
2342 if (vty
->node
== CONFIG_NODE
) {
2343 /* resync in case one of the daemons is somewhere else */
2344 vtysh_execute("end");
2345 vtysh_execute("configure");
2350 DEFUNSH(VTYSH_REALLYALL
, vtysh_exit_all
, vtysh_exit_all_cmd
, "exit",
2351 "Exit current mode and down to previous mode\n")
2353 return vtysh_exit(vty
);
2356 DEFUNSH(VTYSH_REALLYALL
, vtysh_quit_all
, vtysh_quit_all_cmd
, "quit",
2357 "Exit current mode and down to previous mode\n")
2359 return vtysh_exit_all(self
, vty
, argc
, argv
);
2363 DEFUNSH(VTYSH_BGPD
, exit_address_family
, exit_address_family_cmd
,
2364 "exit-address-family", "Exit from Address Family configuration mode\n")
2366 if (vty
->node
== BGP_IPV4_NODE
|| vty
->node
== BGP_IPV4M_NODE
2367 || vty
->node
== BGP_IPV4L_NODE
|| vty
->node
== BGP_VPNV4_NODE
2368 || vty
->node
== BGP_VPNV6_NODE
|| vty
->node
== BGP_IPV6_NODE
2369 || vty
->node
== BGP_IPV6L_NODE
|| vty
->node
== BGP_IPV6M_NODE
2370 || vty
->node
== BGP_EVPN_NODE
2371 || vty
->node
== BGP_FLOWSPECV4_NODE
2372 || vty
->node
== BGP_FLOWSPECV6_NODE
)
2373 vty
->node
= BGP_NODE
;
2377 DEFUNSH(VTYSH_BGPD
, exit_vni
, exit_vni_cmd
, "exit-vni", "Exit from VNI mode\n")
2379 if (vty
->node
== BGP_EVPN_VNI_NODE
)
2380 vty
->node
= BGP_EVPN_NODE
;
2384 DEFUNSH(VTYSH_BGPD
, rpki_exit
, rpki_exit_cmd
, "exit",
2385 "Exit current mode and down to previous mode\n")
2391 DEFUNSH(VTYSH_BGPD
, rpki_quit
, rpki_quit_cmd
, "quit",
2392 "Exit current mode and down to previous mode\n")
2394 return rpki_exit(self
, vty
, argc
, argv
);
2397 DEFUNSH(VTYSH_BGPD
, bmp_exit
, bmp_exit_cmd
, "exit",
2398 "Exit current mode and down to previous mode\n")
2404 DEFUNSH(VTYSH_BGPD
, bmp_quit
, bmp_quit_cmd
, "quit",
2405 "Exit current mode and down to previous mode\n")
2407 return bmp_exit(self
, vty
, argc
, argv
);
2409 #endif /* HAVE_BGPD */
2411 DEFUNSH(VTYSH_VRF
, exit_vrf_config
, exit_vrf_config_cmd
, "exit-vrf",
2412 "Exit from VRF configuration mode\n")
2414 if (vty
->node
== VRF_NODE
)
2415 vty
->node
= CONFIG_NODE
;
2419 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_config
, exit_srv6_config_cmd
, "exit",
2420 "Exit from SRv6 configuration mode\n")
2422 if (vty
->node
== SRV6_NODE
)
2423 vty
->node
= SEGMENT_ROUTING_NODE
;
2427 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_locs_config
, exit_srv6_locs_config_cmd
, "exit",
2428 "Exit from SRv6-locator configuration mode\n")
2430 if (vty
->node
== SRV6_LOCS_NODE
)
2431 vty
->node
= SRV6_NODE
;
2435 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_loc_config
, exit_srv6_loc_config_cmd
, "exit",
2436 "Exit from SRv6-locators configuration mode\n")
2438 if (vty
->node
== SRV6_LOC_NODE
)
2439 vty
->node
= SRV6_LOCS_NODE
;
2444 DEFUNSH(VTYSH_RIPD
, vtysh_exit_ripd
, vtysh_exit_ripd_cmd
, "exit",
2445 "Exit current mode and down to previous mode\n")
2447 return vtysh_exit(vty
);
2450 DEFUNSH(VTYSH_RIPD
, vtysh_quit_ripd
, vtysh_quit_ripd_cmd
, "quit",
2451 "Exit current mode and down to previous mode\n")
2453 return vtysh_exit_ripd(self
, vty
, argc
, argv
);
2455 #endif /* HAVE_RIPD */
2458 DEFUNSH(VTYSH_RIPNGD
, vtysh_exit_ripngd
, vtysh_exit_ripngd_cmd
, "exit",
2459 "Exit current mode and down to previous mode\n")
2461 return vtysh_exit(vty
);
2464 DEFUNSH(VTYSH_RIPNGD
, vtysh_quit_ripngd
, vtysh_quit_ripngd_cmd
, "quit",
2465 "Exit current mode and down to previous mode\n")
2467 return vtysh_exit_ripngd(self
, vty
, argc
, argv
);
2469 #endif /* HAVE_RIPNGD */
2471 DEFUNSH(VTYSH_RMAP
, vtysh_exit_rmap
, vtysh_exit_rmap_cmd
, "exit",
2472 "Exit current mode and down to previous mode\n")
2474 return vtysh_exit(vty
);
2477 DEFUNSH(VTYSH_RMAP
, vtysh_quit_rmap
, vtysh_quit_rmap_cmd
, "quit",
2478 "Exit current mode and down to previous mode\n")
2480 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2484 DEFUNSH(VTYSH_PBRD
, vtysh_exit_pbr_map
, vtysh_exit_pbr_map_cmd
, "exit",
2485 "Exit current mode and down to previous mode\n")
2487 return vtysh_exit(vty
);
2490 DEFUNSH(VTYSH_PBRD
, vtysh_quit_pbr_map
, vtysh_quit_pbr_map_cmd
, "quit",
2491 "Exit current mode and down to previous mode\n")
2493 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2495 #endif /* HAVE_PBRD */
2498 DEFUNSH(VTYSH_BGPD
, vtysh_exit_bgpd
, vtysh_exit_bgpd_cmd
, "exit",
2499 "Exit current mode and down to previous mode\n")
2501 return vtysh_exit(vty
);
2504 DEFUNSH(VTYSH_BGPD
, vtysh_quit_bgpd
, vtysh_quit_bgpd_cmd
, "quit",
2505 "Exit current mode and down to previous mode\n")
2507 return vtysh_exit_bgpd(self
, vty
, argc
, argv
);
2509 #endif /* HAVE_BGPD */
2512 DEFUNSH(VTYSH_OSPFD
, vtysh_exit_ospfd
, vtysh_exit_ospfd_cmd
, "exit",
2513 "Exit current mode and down to previous mode\n")
2515 return vtysh_exit(vty
);
2518 DEFUNSH(VTYSH_OSPFD
, vtysh_quit_ospfd
, vtysh_quit_ospfd_cmd
, "quit",
2519 "Exit current mode and down to previous mode\n")
2521 return vtysh_exit_ospfd(self
, vty
, argc
, argv
);
2523 #endif /* HAVE_OSPFD */
2526 DEFUNSH(VTYSH_EIGRPD
, vtysh_exit_eigrpd
, vtysh_exit_eigrpd_cmd
, "exit",
2527 "Exit current mode and down to previous mode\n")
2529 return vtysh_exit(vty
);
2532 DEFUNSH(VTYSH_EIGRPD
, vtysh_quit_eigrpd
, vtysh_quit_eigrpd_cmd
, "quit",
2533 "Exit current mode and down to previous mode\n")
2535 return vtysh_exit(vty
);
2537 #endif /* HAVE_EIGRPD */
2540 DEFUNSH(VTYSH_BABELD
, vtysh_exit_babeld
, vtysh_exit_babeld_cmd
, "exit",
2541 "Exit current mode and down to previous mode\n")
2543 return vtysh_exit(vty
);
2546 DEFUNSH(VTYSH_BABELD
, vtysh_quit_babeld
, vtysh_quit_babeld_cmd
, "quit",
2547 "Exit current mode and down to previous mode\n")
2549 return vtysh_exit(vty
);
2551 #endif /* HAVE_BABELD */
2554 DEFUNSH(VTYSH_OSPF6D
, vtysh_exit_ospf6d
, vtysh_exit_ospf6d_cmd
, "exit",
2555 "Exit current mode and down to previous mode\n")
2557 return vtysh_exit(vty
);
2560 DEFUNSH(VTYSH_OSPF6D
, vtysh_quit_ospf6d
, vtysh_quit_ospf6d_cmd
, "quit",
2561 "Exit current mode and down to previous mode\n")
2563 return vtysh_exit_ospf6d(self
, vty
, argc
, argv
);
2565 #endif /* HAVE_OSPF6D */
2567 #if defined(HAVE_LDPD)
2568 DEFUNSH(VTYSH_LDPD
, vtysh_exit_ldpd
, vtysh_exit_ldpd_cmd
, "exit",
2569 "Exit current mode and down to previous mode\n")
2571 return vtysh_exit(vty
);
2574 ALIAS(vtysh_exit_ldpd
, vtysh_quit_ldpd_cmd
, "quit",
2575 "Exit current mode and down to previous mode\n")
2579 DEFUNSH(VTYSH_ISISD
, vtysh_exit_isisd
, vtysh_exit_isisd_cmd
, "exit",
2580 "Exit current mode and down to previous mode\n")
2582 return vtysh_exit(vty
);
2585 DEFUNSH(VTYSH_ISISD
, vtysh_quit_isisd
, vtysh_quit_isisd_cmd
, "quit",
2586 "Exit current mode and down to previous mode\n")
2588 return vtysh_exit_isisd(self
, vty
, argc
, argv
);
2590 #endif /* HAVE_ISISD */
2593 DEFUNSH(VTYSH_BFDD
, vtysh_exit_bfdd
, vtysh_exit_bfdd_cmd
, "exit",
2594 "Exit current mode and down to previous mode\n")
2596 return vtysh_exit(vty
);
2599 ALIAS(vtysh_exit_bfdd
, vtysh_quit_bfdd_cmd
, "quit",
2600 "Exit current mode and down to previous mode\n")
2604 DEFUNSH(VTYSH_FABRICD
, vtysh_exit_fabricd
, vtysh_exit_fabricd_cmd
, "exit",
2605 "Exit current mode and down to previous mode\n")
2607 return vtysh_exit(vty
);
2610 DEFUNSH(VTYSH_FABRICD
, vtysh_quit_fabricd
, vtysh_quit_fabricd_cmd
, "quit",
2611 "Exit current mode and down to previous mode\n")
2613 return vtysh_exit_fabricd(self
, vty
, argc
, argv
);
2615 #endif /* HAVE_FABRICD */
2617 DEFUNSH(VTYSH_KEYS
, vtysh_exit_keys
, vtysh_exit_keys_cmd
, "exit",
2618 "Exit current mode and down to previous mode\n")
2620 return vtysh_exit(vty
);
2623 DEFUNSH(VTYSH_KEYS
, vtysh_quit_keys
, vtysh_quit_keys_cmd
, "quit",
2624 "Exit current mode and down to previous mode\n")
2626 return vtysh_exit_keys(self
, vty
, argc
, argv
);
2629 DEFUNSH(VTYSH_SR
, vtysh_exit_sr
, vtysh_exit_sr_cmd
, "exit",
2630 "Exit current mode and down to previous mode\n")
2632 return vtysh_exit(vty
);
2635 DEFUNSH(VTYSH_SR
, vtysh_quit_sr
, vtysh_quit_sr_cmd
, "quit",
2636 "Exit current mode and down to previous mode\n")
2638 return vtysh_exit(vty
);
2641 #if defined(HAVE_PATHD)
2642 DEFUNSH(VTYSH_PATHD
, vtysh_exit_pathd
, vtysh_exit_pathd_cmd
, "exit",
2643 "Exit current mode and down to previous mode\n")
2645 return vtysh_exit(vty
);
2648 DEFUNSH(VTYSH_PATHD
, vtysh_quit_pathd
, vtysh_quit_pathd_cmd
, "quit",
2649 "Exit current mode and down to previous mode\n")
2651 return vtysh_exit_pathd(self
, vty
, argc
, argv
);
2653 #endif /* HAVE_PATHD */
2655 DEFUNSH(VTYSH_ALL
, vtysh_exit_line_vty
, vtysh_exit_line_vty_cmd
, "exit",
2656 "Exit current mode and down to previous mode\n")
2658 return vtysh_exit(vty
);
2661 DEFUNSH(VTYSH_ALL
, vtysh_quit_line_vty
, vtysh_quit_line_vty_cmd
, "quit",
2662 "Exit current mode and down to previous mode\n")
2664 return vtysh_exit_line_vty(self
, vty
, argc
, argv
);
2667 DEFUNSH(VTYSH_INTERFACE
, vtysh_interface
, vtysh_interface_cmd
,
2668 "interface IFNAME [vrf NAME]",
2669 "Select an interface to configure\n"
2670 "Interface's name\n" VRF_CMD_HELP_STR
)
2672 vty
->node
= INTERFACE_NODE
;
2676 DEFUNSH(VTYSH_ZEBRA
, vtysh_pseudowire
, vtysh_pseudowire_cmd
,
2677 "pseudowire IFNAME",
2678 "Static pseudowire configuration\n"
2679 "Pseudowire name\n")
2681 vty
->node
= PW_NODE
;
2685 DEFUNSH(VTYSH_NH_GROUP
,
2686 vtysh_nexthop_group
, vtysh_nexthop_group_cmd
,
2687 "nexthop-group NHGNAME",
2688 "Nexthop Group configuration\n"
2689 "Name of the Nexthop Group\n")
2691 vty
->node
= NH_GROUP_NODE
;
2695 DEFSH(VTYSH_NH_GROUP
, vtysh_no_nexthop_group_cmd
,
2696 "no nexthop-group NHGNAME",
2698 "Nexthop Group Configuration\n"
2699 "Name of the Nexthop Group\n")
2701 DEFUNSH(VTYSH_VRF
, vtysh_vrf
, vtysh_vrf_cmd
, "vrf NAME",
2702 "Select a VRF to configure\n"
2705 vty
->node
= VRF_NODE
;
2709 DEFUNSH(VTYSH_VRF
, vtysh_exit_vrf
, vtysh_exit_vrf_cmd
, "exit",
2710 "Exit current mode and down to previous mode\n")
2712 return vtysh_exit(vty
);
2715 DEFUNSH(VTYSH_VRF
, vtysh_quit_vrf
, vtysh_quit_vrf_cmd
, "quit",
2716 "Exit current mode and down to previous mode\n")
2718 return vtysh_exit_vrf(self
, vty
, argc
, argv
);
2721 DEFUNSH(VTYSH_NH_GROUP
,
2722 vtysh_exit_nexthop_group
, vtysh_exit_nexthop_group_cmd
,
2723 "exit", "Exit current mode and down to previous mode\n")
2725 return vtysh_exit(vty
);
2728 DEFUNSH(VTYSH_NH_GROUP
,
2729 vtysh_quit_nexthop_group
, vtysh_quit_nexthop_group_cmd
,
2730 "quit", "Exit current mode and down to previous mode\n")
2732 return vtysh_exit_nexthop_group(self
, vty
, argc
, argv
);
2735 DEFUNSH(VTYSH_INTERFACE
, vtysh_exit_interface
, vtysh_exit_interface_cmd
, "exit",
2736 "Exit current mode and down to previous mode\n")
2738 return vtysh_exit(vty
);
2741 DEFUNSH(VTYSH_INTERFACE
, vtysh_quit_interface
, vtysh_quit_interface_cmd
, "quit",
2742 "Exit current mode and down to previous mode\n")
2744 return vtysh_exit_interface(self
, vty
, argc
, argv
);
2747 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_pseudowire
, vtysh_exit_pseudowire_cmd
, "exit",
2748 "Exit current mode and down to previous mode\n")
2750 return vtysh_exit(vty
);
2753 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_pseudowire
, vtysh_quit_pseudowire_cmd
, "quit",
2754 "Exit current mode and down to previous mode\n")
2756 return vtysh_exit_pseudowire(self
, vty
, argc
, argv
);
2759 static char *do_prepend(struct vty
*vty
, struct cmd_token
**argv
, int argc
)
2761 const char *argstr
[argc
+ 1];
2764 if (vty
->node
!= VIEW_NODE
) {
2769 for (i
= 0; i
< argc
; i
++)
2770 argstr
[i
+ off
] = argv
[i
]->arg
;
2772 return frrstr_join(argstr
, argc
+ off
, " ");
2775 #pragma GCC diagnostic push
2776 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2777 /* 'headline' is a format string with a %s for the daemon name
2779 * Also for some reason GCC emits the warning on the end of the function
2780 * (optimization maybe?) rather than on the vty_out line, so this pragma
2781 * wraps the entire function rather than just the vty_out line.
2784 static int show_per_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2785 const char *headline
)
2788 int ret
= CMD_SUCCESS
;
2789 char *line
= do_prepend(vty
, argv
, argc
);
2791 for (i
= 0; i
< array_size(vtysh_client
); i
++)
2792 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
2793 vty_out(vty
, headline
, vtysh_client
[i
].name
);
2794 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
2798 XFREE(MTYPE_TMP
, line
);
2802 #pragma GCC diagnostic pop
2804 static int show_one_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2808 char *line
= do_prepend(vty
, argv
, argc
);
2810 ret
= vtysh_client_execute_name(name
, line
);
2812 XFREE(MTYPE_TMP
, line
);
2817 DEFUN (vtysh_show_thread_timer
,
2818 vtysh_show_thread_timer_cmd
,
2819 "show thread timers",
2821 "Thread information\n"
2822 "Show all timers and how long they have in the system\n")
2824 return show_per_daemon(vty
, argv
, argc
, "Thread timers for %s:\n");
2827 DEFUN (vtysh_show_poll
,
2828 vtysh_show_poll_cmd
,
2831 "Thread information\n"
2832 "Thread Poll Information\n")
2834 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2837 DEFUN (vtysh_show_thread
,
2838 vtysh_show_thread_cmd
,
2839 "show thread cpu [FILTER]",
2841 "Thread information\n"
2842 "Thread CPU usage\n"
2843 "Display filter (rwtexb)\n")
2845 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2848 DEFUN (vtysh_show_work_queues
,
2849 vtysh_show_work_queues_cmd
,
2852 "Work Queue information\n")
2854 return show_per_daemon(vty
, argv
, argc
,
2855 "Work queue statistics for %s:\n");
2858 DEFUN (vtysh_show_work_queues_daemon
,
2859 vtysh_show_work_queues_daemon_cmd
,
2860 "show work-queues " DAEMONS_LIST
,
2862 "Work Queue information\n"
2865 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2868 DEFUNSH(VTYSH_ZEBRA
, vtysh_link_params
, vtysh_link_params_cmd
, "link-params",
2871 vty
->node
= LINK_PARAMS_NODE
;
2875 DEFUNSH(VTYSH_ZEBRA
, exit_link_params
, exit_link_params_cmd
, "exit-link-params",
2876 "Exit from Link Params configuration node\n")
2878 if (vty
->node
== LINK_PARAMS_NODE
)
2879 vty
->node
= INTERFACE_NODE
;
2883 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_link_params
, vtysh_exit_link_params_cmd
, "exit",
2884 "Exit current mode and down to previous mode\n")
2886 if (vty
->node
== LINK_PARAMS_NODE
)
2887 vty
->node
= INTERFACE_NODE
;
2891 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_link_params
, vtysh_quit_link_params_cmd
, "quit",
2892 "Exit current mode and down to previous mode\n")
2894 return vtysh_exit_link_params(self
, vty
, argc
, argv
);
2897 DEFUNSH_HIDDEN (0x00,
2899 vtysh_debug_all_cmd
,
2903 "Toggle all debugs on or off\n")
2908 DEFUN (vtysh_show_debugging
,
2909 vtysh_show_debugging_cmd
,
2914 return show_per_daemon(vty
, argv
, argc
, "");
2917 DEFUN (vtysh_show_debugging_hashtable
,
2918 vtysh_show_debugging_hashtable_cmd
,
2919 "show debugging hashtable [statistics]",
2922 "Statistics about hash tables\n"
2923 "Statistics about hash tables\n")
2925 bool stats
= strmatch(argv
[argc
- 1]->text
, "statistics");
2929 "Load factor (LF) - average number of elements across all buckets\n");
2931 "Full load factor (FLF) - average number of elements across full buckets\n\n");
2933 "Standard deviation (SD) is calculated for both the LF and FLF\n");
2935 "and indicates the typical deviation of bucket chain length\n");
2936 vty_out(vty
, "from the value in the corresponding load factor.\n\n");
2938 return show_per_daemon(vty
, argv
, stats
? argc
- 1 : argc
,
2939 "Hashtable statistics for %s:\n");
2942 DEFUN (vtysh_show_error_code
,
2943 vtysh_show_error_code_cmd
,
2944 "show error <(1-4294967296)|all> [json]",
2946 "Information on errors\n"
2947 "Error code to get info about\n"
2948 "Information on all errors\n"
2953 if (!strmatch(argv
[2]->text
, "all"))
2954 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2956 /* If it's not a shared code, send it to all the daemons */
2957 if (arg
< LIB_FERR_START
|| arg
> LIB_FERR_END
) {
2958 show_per_daemon(vty
, argv
, argc
, "");
2959 /* Otherwise, print it ourselves to avoid duplication */
2961 bool json
= strmatch(argv
[argc
- 1]->text
, "json");
2963 if (!strmatch(argv
[2]->text
, "all"))
2964 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2966 log_ref_display(vty
, arg
, json
);
2973 DEFUN_HIDDEN (show_config_running
,
2974 show_config_running_cmd
,
2975 "show configuration running\
2976 [<json|xml> [translate WORD]]\
2977 [with-defaults] " DAEMONS_LIST
,
2979 "Configuration information\n"
2980 "Running configuration\n"
2981 "Change output format to JSON\n"
2982 "Change output format to XML\n"
2983 "Translate output\n"
2984 "YANG module translator\n"
2985 "Show default values\n"
2988 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2991 DEFUN (show_yang_operational_data
,
2992 show_yang_operational_data_cmd
,
2993 "show yang operational-data XPATH\
3000 "YANG information\n"
3001 "Show YANG operational data\n"
3002 "XPath expression specifying the YANG data path\n"
3003 "Set the output format\n"
3004 "JavaScript Object Notation\n"
3005 "Extensible Markup Language\n"
3006 "Translate operational data\n"
3007 "YANG module translator\n"
3008 "Merge configuration data\n"
3011 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3014 DEFUN(show_yang_module
, show_yang_module_cmd
,
3015 "show yang module [module-translator WORD] " DAEMONS_LIST
,
3017 "YANG information\n"
3018 "Show loaded modules\n"
3019 "YANG module translator\n"
3020 "YANG module translator\n" DAEMONS_STR
)
3022 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3025 DEFUN(show_yang_module_detail
, show_yang_module_detail_cmd
,
3027 [module-translator WORD]\
3028 WORD <compiled|summary|tree|yang|yin> " DAEMONS_LIST
,
3030 "YANG information\n"
3031 "Show loaded modules\n"
3032 "YANG module translator\n"
3033 "YANG module translator\n"
3035 "Display compiled module in YANG format\n"
3036 "Display summary information about the module\n"
3037 "Display module in the tree (RFC 8340) format\n"
3038 "Display module in the YANG format\n"
3039 "Display module in the YIN format\n" DAEMONS_STR
)
3041 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3045 DEFUNSH(VTYSH_ALL
, debug_nb
,
3047 "[no] debug northbound\
3049 callbacks [{configuration|state|rpc}]\
3056 "Northbound debugging\n"
3063 "libyang debugging\n")
3068 DEFUN (vtysh_show_history
,
3069 vtysh_show_history_cmd
,
3072 "The list of commands stored in history\n")
3074 HIST_ENTRY
**hlist
= history_list();
3078 vty_out(vty
, "%s\n", hlist
[i
]->line
);
3085 DEFUN (vtysh_show_memory
,
3086 vtysh_show_memory_cmd
,
3087 "show memory [" DAEMONS_LIST
"]",
3089 "Memory statistics\n"
3093 return show_one_daemon(vty
, argv
, argc
- 1,
3094 argv
[argc
- 1]->text
);
3096 return show_per_daemon(vty
, argv
, argc
, "Memory statistics for %s:\n");
3099 DEFUN (vtysh_show_modules
,
3100 vtysh_show_modules_cmd
,
3105 return show_per_daemon(vty
, argv
, argc
, "Module information for %s:\n");
3108 /* Logging commands. */
3109 DEFUN (vtysh_show_logging
,
3110 vtysh_show_logging_cmd
,
3113 "Show current logging configuration\n")
3115 return show_per_daemon(vty
, argv
, argc
,
3116 "Logging configuration for %s:\n");
3119 DEFUNSH(VTYSH_ALL
, vtysh_debug_memstats
,
3120 vtysh_debug_memstats_cmd
, "[no] debug memstats-at-exit",
3123 "Print memory statistics at exit\n")
3128 DEFUN(vtysh_debug_uid_backtrace
,
3129 vtysh_debug_uid_backtrace_cmd
,
3130 "[no] debug unique-id UID backtrace",
3133 "Options per individual log message, by unique ID\n"
3134 "Log message unique ID (XXXXX-XXXXX)\n"
3135 "Add backtrace to log when message is printed\n")
3137 unsigned int i
, ok
= 0;
3138 int err
= CMD_SUCCESS
, ret
;
3142 if (!strcmp(argv
[0]->text
, "no")) {
3144 snprintfrr(line
, sizeof(line
),
3145 "no debug unique-id %s backtrace", uid
);
3148 snprintfrr(line
, sizeof(line
), "debug unique-id %s backtrace",
3152 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3153 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
3154 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3159 case CMD_ERR_NOTHING_TODO
:
3160 /* ignore this daemon
3162 * note this doesn't need to handle instances
3163 * of the same daemon individually because
3164 * the same daemon will have the same UIDs
3168 if (err
== CMD_SUCCESS
)
3174 if (err
== CMD_SUCCESS
&& !ok
) {
3175 vty_out(vty
, "%% no running daemon recognizes unique-ID %s\n",
3182 DEFUNSH(VTYSH_ALL
, vtysh_allow_reserved_ranges
, vtysh_allow_reserved_ranges_cmd
,
3183 "allow-reserved-ranges",
3184 "Allow using IPv4 (Class E) reserved IP space\n")
3189 DEFUNSH(VTYSH_ALL
, no_vtysh_allow_reserved_ranges
,
3190 no_vtysh_allow_reserved_ranges_cmd
, "no allow-reserved-ranges",
3191 NO_STR
"Allow using IPv4 (Class E) reserved IP space\n")
3196 DEFUNSH(VTYSH_ALL
, vtysh_service_password_encrypt
,
3197 vtysh_service_password_encrypt_cmd
, "service password-encryption",
3198 "Set up miscellaneous service\n"
3199 "Enable encrypted passwords\n")
3204 DEFUNSH(VTYSH_ALL
, no_vtysh_service_password_encrypt
,
3205 no_vtysh_service_password_encrypt_cmd
, "no service password-encryption",
3207 "Set up miscellaneous service\n"
3208 "Enable encrypted passwords\n")
3213 DEFUNSH(VTYSH_ALL
, vtysh_config_password
, vtysh_password_cmd
,
3214 "password [(8-8)] LINE",
3215 "Modify the terminal connection password\n"
3216 "Specifies a HIDDEN password will follow\n"
3217 "The password string\n")
3222 DEFUNSH(VTYSH_ALL
, no_vtysh_config_password
, no_vtysh_password_cmd
,
3223 "no password", NO_STR
3224 "Modify the terminal connection password\n")
3226 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3231 DEFUNSH(VTYSH_ALL
, vtysh_config_enable_password
, vtysh_enable_password_cmd
,
3232 "enable password [(8-8)] LINE",
3233 "Modify enable password parameters\n"
3234 "Assign the privileged level password\n"
3235 "Specifies a HIDDEN password will follow\n"
3236 "The 'enable' password string\n")
3241 DEFUNSH(VTYSH_ALL
, no_vtysh_config_enable_password
,
3242 no_vtysh_enable_password_cmd
, "no enable password", NO_STR
3243 "Modify enable password parameters\n"
3244 "Assign the privileged level password\n")
3246 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3251 DEFUN (vtysh_write_terminal
,
3252 vtysh_write_terminal_cmd
,
3253 "write terminal ["DAEMONS_LIST
"] [no-header]",
3254 "Write running configuration to memory, network, or terminal\n"
3255 "Write to terminal\n"
3257 "Skip \"Building configuration...\" header\n")
3260 char line
[] = "do write terminal";
3262 if (!strcmp(argv
[argc
- 1]->arg
, "no-header"))
3265 vty_out(vty
, "Building configuration...\n");
3266 vty_out(vty
, "\nCurrent configuration:\n");
3267 vty_out(vty
, "!\n");
3270 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3272 || (strmatch(vtysh_client
[i
].name
, argv
[2]->text
)))
3273 vtysh_client_config(&vtysh_client
[i
], line
);
3275 /* Integrate vtysh specific configuration. */
3276 vty_open_pager(vty
);
3277 vtysh_config_write();
3278 vtysh_config_dump();
3279 vty_close_pager(vty
);
3280 vty_out(vty
, "end\n");
3285 DEFUN (vtysh_show_running_config
,
3286 vtysh_show_running_config_cmd
,
3287 "show running-config ["DAEMONS_LIST
"] [no-header]",
3289 "Current operating configuration\n"
3291 "Skip \"Building configuration...\" header\n")
3293 return vtysh_write_terminal(self
, vty
, argc
, argv
);
3296 DEFUN (vtysh_integrated_config
,
3297 vtysh_integrated_config_cmd
,
3298 "service integrated-vtysh-config",
3299 "Set up miscellaneous service\n"
3300 "Write configuration into integrated file\n")
3302 vtysh_write_integrated
= WRITE_INTEGRATED_YES
;
3306 DEFUN (no_vtysh_integrated_config
,
3307 no_vtysh_integrated_config_cmd
,
3308 "no service integrated-vtysh-config",
3310 "Set up miscellaneous service\n"
3311 "Write configuration into integrated file\n")
3313 vtysh_write_integrated
= WRITE_INTEGRATED_NO
;
3317 static void backup_config_file(const char *fbackup
)
3319 char *integrate_sav
= NULL
;
3321 size_t integrate_sav_sz
= strlen(fbackup
) + strlen(CONF_BACKUP_EXT
) + 1;
3322 integrate_sav
= malloc(integrate_sav_sz
);
3323 strlcpy(integrate_sav
, fbackup
, integrate_sav_sz
);
3324 strlcat(integrate_sav
, CONF_BACKUP_EXT
, integrate_sav_sz
);
3326 /* Move current configuration file to backup config file. */
3327 if (unlink(integrate_sav
) != 0 && errno
!= ENOENT
)
3328 vty_out(vty
, "Unlink failed for %s: %s\n", integrate_sav
,
3330 if (rename(fbackup
, integrate_sav
) != 0 && errno
!= ENOENT
)
3331 vty_out(vty
, "Error renaming %s to %s: %s\n", fbackup
,
3332 integrate_sav
, strerror(errno
));
3333 free(integrate_sav
);
3336 int vtysh_write_config_integrated(void)
3339 char line
[] = "do write terminal";
3343 struct passwd
*pwentry
;
3346 struct group
*grentry
;
3353 vty_out(vty
, "Building Configuration...\n");
3355 backup_config_file(frr_config
);
3356 fp
= fopen(frr_config
, "w");
3359 "%% Error: failed to open configuration file %s: %s\n",
3360 frr_config
, safe_strerror(errno
));
3361 return CMD_WARNING_CONFIG_FAILED
;
3365 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3366 vtysh_client_config(&vtysh_client
[i
], line
);
3368 vtysh_config_write();
3369 vty
->of_saved
= vty
->of
;
3371 vtysh_config_dump();
3372 vty
->of
= vty
->of_saved
;
3374 if (fchmod(fd
, CONFIGFILE_MASK
) != 0) {
3375 printf("%% Warning: can't chmod configuration file %s: %s\n",
3376 frr_config
, safe_strerror(errno
));
3381 pwentry
= getpwnam(FRR_USER
);
3383 uid
= pwentry
->pw_uid
;
3385 printf("%% Warning: could not look up user \"%s\"\n", FRR_USER
);
3390 grentry
= getgrnam(FRR_GROUP
);
3392 gid
= grentry
->gr_gid
;
3394 printf("%% Warning: could not look up group \"%s\"\n",
3400 if (!fstat(fd
, &st
)) {
3401 if (st
.st_uid
== uid
)
3403 if (st
.st_gid
== gid
)
3405 if ((uid
!= (uid_t
)-1 || gid
!= (gid_t
)-1)
3406 && fchown(fd
, uid
, gid
)) {
3407 printf("%% Warning: can't chown configuration file %s: %s\n",
3408 frr_config
, safe_strerror(errno
));
3412 printf("%% Warning: stat() failed on %s: %s\n", frr_config
,
3413 safe_strerror(errno
));
3417 if (fflush(fp
) != 0) {
3418 printf("%% Warning: fflush() failed on %s: %s\n", frr_config
,
3419 safe_strerror(errno
));
3423 if (fsync(fd
) < 0) {
3424 printf("%% Warning: fsync() failed on %s: %s\n", frr_config
,
3425 safe_strerror(errno
));
3431 printf("Integrated configuration saved to %s\n", frr_config
);
3439 DEFUN_HIDDEN(start_config
, start_config_cmd
, "XFRR_start_configuration",
3440 "The Beginning of Configuration\n")
3443 char line
[] = "XFRR_start_configuration";
3445 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3446 vtysh_client_execute(&vtysh_client
[i
], line
);
3451 DEFUN_HIDDEN(end_config
, end_config_cmd
, "XFRR_end_configuration",
3452 "The End of Configuration\n")
3455 char line
[] = "XFRR_end_configuration";
3457 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3458 vtysh_client_execute(&vtysh_client
[i
], line
);
3463 static bool want_config_integrated(void)
3467 switch (vtysh_write_integrated
) {
3468 case WRITE_INTEGRATED_UNSPECIFIED
:
3469 if (stat(frr_config
, &s
) && errno
== ENOENT
)
3472 case WRITE_INTEGRATED_NO
:
3474 case WRITE_INTEGRATED_YES
:
3480 DEFUN (vtysh_write_memory
,
3481 vtysh_write_memory_cmd
,
3482 "write [<memory|file>]",
3483 "Write running configuration to memory, network, or terminal\n"
3484 "Write configuration to the file (same as write file)\n"
3485 "Write configuration to the file (same as write memory)\n")
3487 int ret
= CMD_SUCCESS
;
3488 char line
[] = "do write memory";
3491 vty_out(vty
, "Note: this version of vtysh never writes vtysh.conf\n");
3493 /* If integrated frr.conf explicitly set. */
3494 if (want_config_integrated()) {
3495 ret
= CMD_WARNING_CONFIG_FAILED
;
3497 /* first attempt to use watchfrr if it's available */
3498 bool used_watchfrr
= false;
3500 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3501 if (vtysh_client
[i
].flag
== VTYSH_WATCHFRR
)
3503 if (i
< array_size(vtysh_client
) && vtysh_client
[i
].fd
!= -1) {
3504 used_watchfrr
= true;
3505 ret
= vtysh_client_execute(&vtysh_client
[i
],
3506 "do write integrated");
3510 * If we didn't use watchfrr, fallback to writing the config
3513 if (!used_watchfrr
) {
3514 printf("\nWarning: attempting direct configuration write without watchfrr.\nFile permissions and ownership may be incorrect, or write may fail.\n\n");
3515 ret
= vtysh_write_config_integrated();
3520 vty_out(vty
, "Building Configuration...\n");
3522 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3523 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3528 DEFUN (vtysh_copy_running_config
,
3529 vtysh_copy_running_config_cmd
,
3530 "copy running-config startup-config",
3531 "Copy from one file to another\n"
3532 "Copy from current system configuration\n"
3533 "Copy to startup configuration\n")
3535 return vtysh_write_memory(self
, vty
, argc
, argv
);
3538 DEFUN (vtysh_copy_to_running
,
3539 vtysh_copy_to_running_cmd
,
3540 "copy FILENAME running-config",
3541 "Apply a configuration file\n"
3542 "Configuration file to read\n"
3543 "Apply to current configuration\n")
3546 const char *fname
= argv
[1]->arg
;
3548 ret
= vtysh_read_config(fname
, true);
3550 /* Return to enable mode - the 'read_config' api leaves us up a level */
3551 vtysh_execute_no_pager("enable");
3556 DEFUN (vtysh_terminal_paginate
,
3557 vtysh_terminal_paginate_cmd
,
3558 "[no] terminal paginate",
3560 "Set terminal line parameters\n"
3561 "Use pager for output scrolling\n")
3563 free(vtysh_pager_name
);
3564 vtysh_pager_name
= NULL
;
3566 if (strcmp(argv
[0]->text
, "no"))
3567 vtysh_pager_envdef(true);
3571 DEFUN (vtysh_terminal_length
,
3572 vtysh_terminal_length_cmd
,
3573 "[no] terminal length (0-4294967295)",
3575 "Set terminal line parameters\n"
3576 "Set number of lines on a screen\n"
3577 "Number of lines on screen (0 for no pausing, nonzero to use pager)\n")
3580 unsigned long lines
;
3582 free(vtysh_pager_name
);
3583 vtysh_pager_name
= NULL
;
3585 if (!strcmp(argv
[0]->text
, "no") || !strcmp(argv
[1]->text
, "no")) {
3586 /* "terminal no length" = use VTYSH_PAGER */
3587 vtysh_pager_envdef(true);
3591 lines
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
3594 "%% The \"terminal length\" command is deprecated and its value is ignored.\n"
3595 "%% Please use \"terminal paginate\" instead with OS TTY length handling.\n");
3596 vtysh_pager_envdef(true);
3602 ALIAS_DEPRECATED(vtysh_terminal_length
,
3603 vtysh_terminal_no_length_cmd
,
3604 "terminal no length",
3605 "Set terminal line parameters\n"
3607 "Set number of lines on a screen\n")
3609 DEFUN (vtysh_show_daemons
,
3610 vtysh_show_daemons_cmd
,
3613 "Show list of running daemons\n")
3617 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3618 if (vtysh_client
[i
].fd
>= 0)
3619 vty_out(vty
, " %s", vtysh_client
[i
].name
);
3625 struct visual_prio
{
3626 /* 4 characters for nice alignment */
3629 int c256_background
;
3633 /* clang-format off */
3634 struct visual_prio visual_prios
[] = {
3636 .label
= "\e[31;1mEMRG",
3637 .c256_background
= 53,
3638 .c256_formatarg
= 225,
3641 .label
= "\e[31;1mALRT",
3642 .c256_background
= 53,
3643 .c256_formatarg
= 225,
3646 .label
= "\e[31;1mCRIT",
3647 .c256_background
= 53,
3648 .c256_formatarg
= 225,
3651 .label
= "\e[38;5;202mERR!",
3652 .c256_background
= 52,
3653 .c256_formatarg
= 224,
3656 .label
= "\e[38;5;222mWARN",
3657 .c256_background
= 58,
3658 .c256_formatarg
= 230,
3662 .c256_background
= 234,
3663 .c256_formatarg
= 195,
3666 .label
= "\e[38;5;192mINFO",
3667 .c256_background
= 236,
3668 .c256_formatarg
= 195,
3671 .label
= "\e[38;5;116mDEBG",
3672 .c256_background
= 238,
3673 .c256_formatarg
= 195,
3676 /* clang-format on */
3678 static void vtysh_log_print(struct vtysh_client
*vclient
,
3679 struct zlog_live_hdr
*hdr
, const char *text
)
3681 size_t textlen
= hdr
->textlen
, textpos
= 0;
3682 time_t ts
= hdr
->ts_sec
;
3683 struct visual_prio
*vis
;
3687 if (hdr
->prio
>= array_size(visual_prios
))
3688 vis
= &visual_prios
[LOG_CRIT
];
3690 vis
= &visual_prios
[hdr
->prio
];
3692 localtime_r(&ts
, &tm
);
3693 strftime(ts_buf
, sizeof(ts_buf
), "%Y-%m-%d %H:%M:%S", &tm
);
3696 const char *label
= vis
->label
+ strlen(vis
->label
) - 4;
3698 fprintf(stderr
, "%s.%03u [%s] %s: %.*s\n", ts_buf
,
3699 hdr
->ts_nsec
/ 1000000U, label
, vclient
->name
,
3700 (int)textlen
, text
);
3705 "\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",
3706 vis
->c256_background
, ts_buf
, hdr
->ts_nsec
/ 1000000U,
3707 vis
->label
, vclient
->name
);
3709 for (size_t fmtpos
= 0; fmtpos
< hdr
->n_argpos
; fmtpos
++) {
3710 struct fmt_outpos
*fmt
= &hdr
->argpos
[fmtpos
];
3712 if (fmt
->off_start
< textpos
|| fmt
->off_end
< fmt
->off_start
||
3713 fmt
->off_end
> textlen
)
3716 while (fmt
->off_end
> fmt
->off_start
&&
3717 text
[fmt
->off_end
- 1] == ' ')
3720 fprintf(stderr
, "%.*s\e[38;5;%dm%.*s\e[38;5;251m",
3721 (int)(fmt
->off_start
- textpos
), text
+ textpos
,
3722 vis
->c256_formatarg
,
3723 (int)(fmt
->off_end
- fmt
->off_start
),
3724 text
+ fmt
->off_start
);
3725 textpos
= fmt
->off_end
;
3727 fprintf(stderr
, "%.*s\033[K\033[m\n", (int)(textlen
- textpos
),
3731 static void vtysh_log_read(struct thread
*thread
)
3733 struct vtysh_client
*vclient
= THREAD_ARG(thread
);
3735 struct zlog_live_hdr hdr
;
3741 thread_add_read(master
, vtysh_log_read
, vclient
, vclient
->log_fd
,
3742 &vclient
->log_reader
);
3744 ret
= recv(vclient
->log_fd
, &buf
, sizeof(buf
), 0);
3746 if (ret
< 0 && ERRNO_IO_RETRY(errno
))
3749 if (stderr_stdout_same
) {
3750 #ifdef HAVE_RL_CLEAR_VISIBLE_LINE
3751 rl_clear_visible_line();
3761 buf
.text
[0] = '\0'; /* coverity */
3764 snprintfrr(buf
.text
, sizeof(buf
.text
),
3765 "log monitor connection error: %m");
3768 buf
.text
, sizeof(buf
.text
),
3769 "log monitor connection closed unexpectedly");
3770 buf
.hdr
.textlen
= strlen(buf
.text
);
3772 THREAD_OFF(vclient
->log_reader
);
3773 close(vclient
->log_fd
);
3774 vclient
->log_fd
= -1;
3776 clock_gettime(CLOCK_REALTIME
, &ts
);
3777 buf
.hdr
.ts_sec
= ts
.tv_sec
;
3778 buf
.hdr
.ts_nsec
= ts
.tv_nsec
;
3779 buf
.hdr
.prio
= LOG_ERR
;
3781 buf
.hdr
.texthdrlen
= 0;
3782 buf
.hdr
.n_argpos
= 0;
3784 int32_t lost_msgs
= buf
.hdr
.lost_msgs
- vclient
->lost_msgs
;
3786 if (lost_msgs
> 0) {
3787 vclient
->lost_msgs
= buf
.hdr
.lost_msgs
;
3789 "%d log messages from %s lost (vtysh reading too slowly)\n",
3790 lost_msgs
, vclient
->name
);
3794 text
= buf
.text
+ sizeof(buf
.hdr
.argpos
[0]) * buf
.hdr
.n_argpos
;
3795 vtysh_log_print(vclient
, &buf
.hdr
, text
);
3797 if (stderr_stdout_same
)
3798 rl_forced_update_display();
3804 /* clippy/clidef can't process the DEFPY below without some value for this */
3805 #define DAEMONS_LIST "daemon"
3808 DEFPY (vtysh_terminal_monitor
,
3809 vtysh_terminal_monitor_cmd
,
3810 "terminal monitor ["DAEMONS_LIST
"]$daemon",
3811 "Set terminal line parameters\n"
3812 "Receive log messages to active VTY session\n"
3815 static const char line
[] = "terminal monitor";
3816 int ret_all
= CMD_SUCCESS
, ret
, fd
;
3819 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3820 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3822 if (daemon
&& strcmp(vclient
->name
, daemon
))
3825 for (; vclient
; vclient
= vclient
->next
) {
3826 if (vclient
->log_fd
!= -1) {
3827 vty_out(vty
, "%% %s: already monitoring logs\n",
3834 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, &fd
);
3836 set_nonblocking(fd
);
3837 vclient
->log_fd
= fd
;
3838 thread_add_read(master
, vtysh_log_read
, vclient
,
3840 &vclient
->log_reader
);
3842 if (ret
!= CMD_SUCCESS
) {
3843 vty_out(vty
, "%% failed to enable logs on %s\n",
3845 ret_all
= CMD_WARNING
;
3851 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3853 "%% command had no effect, relevant daemons not connected?\n");
3854 ret_all
= CMD_WARNING
;
3859 DEFPY (no_vtysh_terminal_monitor
,
3860 no_vtysh_terminal_monitor_cmd
,
3861 "no terminal monitor ["DAEMONS_LIST
"]$daemon",
3863 "Set terminal line parameters\n"
3864 "Receive log messages to active VTY session\n"
3867 static const char line
[] = "no terminal monitor";
3868 int ret_all
= CMD_SUCCESS
, ret
;
3871 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3872 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3874 if (daemon
&& strcmp(vclient
->name
, daemon
))
3877 for (; vclient
; vclient
= vclient
->next
) {
3878 /* run this even if log_fd == -1, in case something
3881 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, NULL
);
3882 if (ret
!= CMD_SUCCESS
) {
3884 "%% failed to disable logs on %s\n",
3886 ret_all
= CMD_WARNING
;
3890 /* with this being a datagram socket, we can't expect
3891 * a close notification...
3893 if (vclient
->log_fd
!= -1) {
3894 THREAD_OFF(vclient
->log_reader
);
3896 close(vclient
->log_fd
);
3897 vclient
->log_fd
= -1;
3902 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3904 "%% command had no effect, relevant daemons not connected?\n");
3905 ret_all
= CMD_WARNING
;
3911 /* Execute command in child process. */
3912 static void execute_command(const char *command
, int argc
, const char *arg1
,
3922 /* Failure of fork(). */
3923 fprintf(stderr
, "Can't fork: %s\n", safe_strerror(errno
));
3925 } else if (pid
== 0) {
3926 /* This is child process. */
3929 execlp(command
, command
, (const char *)NULL
);
3932 execlp(command
, command
, arg1
, (const char *)NULL
);
3935 execlp(command
, command
, arg1
, arg2
,
3936 (const char *)NULL
);
3940 /* When execlp suceed, this part is not executed. */
3941 fprintf(stderr
, "Can't execute %s: %s\n", command
,
3942 safe_strerror(errno
));
3945 /* This is parent. */
3947 wait4(pid
, &status
, 0, NULL
);
3955 "Send echo messages\n"
3956 "Ping destination address or hostname\n")
3960 argv_find(argv
, argc
, "WORD", &idx
);
3961 execute_command("ping", 1, argv
[idx
]->arg
, NULL
);
3965 DEFUN(vtysh_motd
, vtysh_motd_cmd
, "show motd", SHOW_STR
"Show motd\n")
3971 ALIAS(vtysh_ping
, vtysh_ping_ip_cmd
, "ping ip WORD",
3972 "Send echo messages\n"
3974 "Ping destination address or hostname\n")
3976 DEFUN (vtysh_traceroute
,
3977 vtysh_traceroute_cmd
,
3979 "Trace route to destination\n"
3980 "Trace route to destination address or hostname\n")
3984 argv_find(argv
, argc
, "WORD", &idx
);
3985 execute_command("traceroute", 1, argv
[idx
]->arg
, NULL
);
3989 ALIAS(vtysh_traceroute
, vtysh_traceroute_ip_cmd
, "traceroute ip WORD",
3990 "Trace route to destination\n"
3992 "Trace route to destination address or hostname\n")
3994 DEFUN (vtysh_mtrace
,
3996 "mtrace WORD [WORD]",
3997 "Multicast trace route to multicast source\n"
3998 "Multicast trace route to multicast source address\n"
3999 "Multicast trace route for multicast group address\n")
4002 execute_command("mtracebis", 1, argv
[1]->arg
, NULL
);
4004 execute_command("mtracebis", 2, argv
[1]->arg
, argv
[2]->arg
);
4011 "Send echo messages\n"
4013 "Ping destination address or hostname\n")
4015 execute_command("ping6", 1, argv
[2]->arg
, NULL
);
4019 DEFUN (vtysh_traceroute6
,
4020 vtysh_traceroute6_cmd
,
4021 "traceroute ipv6 WORD",
4022 "Trace route to destination\n"
4024 "Trace route to destination address or hostname\n")
4026 execute_command("traceroute6", 1, argv
[2]->arg
, NULL
);
4030 #if CONFDATE > 20240201
4031 CPP_NOTICE("Remove HAVE_SHELL_ACCESS and it's documentation");
4033 #if defined(HAVE_SHELL_ACCESS)
4034 DEFUN (vtysh_telnet
,
4037 "Open a telnet connection\n"
4038 "IP address or hostname of a remote system\n")
4040 execute_command("telnet", 1, argv
[1]->arg
, NULL
);
4044 DEFUN (vtysh_telnet_port
,
4045 vtysh_telnet_port_cmd
,
4047 "Open a telnet connection\n"
4048 "IP address or hostname of a remote system\n"
4049 "TCP Port number\n")
4051 execute_command("telnet", 2, argv
[1]->arg
, argv
[2]->arg
);
4058 "Open an ssh connection\n"
4061 execute_command("ssh", 1, argv
[1]->arg
, NULL
);
4065 DEFUN (vtysh_start_shell
,
4066 vtysh_start_shell_cmd
,
4068 "Start UNIX shell\n")
4070 execute_command("sh", 0, NULL
, NULL
);
4074 DEFUN (vtysh_start_bash
,
4075 vtysh_start_bash_cmd
,
4077 "Start UNIX shell\n"
4080 execute_command("bash", 0, NULL
, NULL
);
4084 DEFUN (vtysh_start_zsh
,
4085 vtysh_start_zsh_cmd
,
4087 "Start UNIX shell\n"
4090 execute_command("zsh", 0, NULL
, NULL
);
4097 "list [permutations]",
4098 "Print command list\n"
4099 "Print all possible command permutations\n")
4101 return cmd_list_cmds(vty
, argc
== 2);
4104 DEFUN (vtysh_output_file
,
4105 vtysh_output_file_cmd
,
4107 "Direct vtysh output to file\n"
4108 "Direct vtysh output to file\n"
4109 "Path to dump output to\n")
4111 const char *path
= argv
[argc
- 1]->arg
;
4112 vty
->of
= fopen(path
, "a");
4114 vty_out(vty
, "Failed to open file '%s': %s\n", path
,
4115 safe_strerror(errno
));
4121 DEFUN (no_vtysh_output_file
,
4122 no_vtysh_output_file_cmd
,
4123 "no output file [FILE]",
4125 "Direct vtysh output to file\n"
4126 "Direct vtysh output to file\n"
4127 "Path to dump output to\n")
4129 if (vty
->of
!= stdout
) {
4139 "Find CLI command matching a regular expression\n"
4140 "Search pattern (POSIX regex)\n")
4142 return cmd_find_cmds(vty
, argv
, argc
);
4145 DEFUN_HIDDEN(show_cli_graph_vtysh
,
4146 show_cli_graph_vtysh_cmd
,
4150 "Dump current command space as DOT graph\n")
4152 struct cmd_node
*cn
= vector_slot(cmdvec
, vty
->node
);
4153 char *dot
= cmd_graph_dump_dot(cn
->cmdgraph
);
4155 vty_out(vty
, "%s\n", dot
);
4156 XFREE(MTYPE_TMP
, dot
);
4160 static void vtysh_install_default(enum node_type node
)
4162 _install_element(node
, &config_list_cmd
);
4163 _install_element(node
, &find_cmd
);
4164 _install_element(node
, &show_cli_graph_vtysh_cmd
);
4165 _install_element(node
, &vtysh_output_file_cmd
);
4166 _install_element(node
, &no_vtysh_output_file_cmd
);
4169 /* Making connection to protocol daemon. */
4170 static int vtysh_connect(struct vtysh_client
*vclient
)
4174 struct sockaddr_un addr
;
4178 if (!vclient
->path
[0])
4179 snprintf(vclient
->path
, sizeof(vclient
->path
), "%s/%s.vty",
4180 vtydir
, vclient
->name
);
4181 path
= vclient
->path
;
4183 /* Stat socket to see if we have permission to access it. */
4184 ret
= stat(path
, &s_stat
);
4185 if (ret
< 0 && errno
!= ENOENT
) {
4186 fprintf(stderr
, "vtysh_connect(%s): stat = %s\n", path
,
4187 safe_strerror(errno
));
4192 if (!S_ISSOCK(s_stat
.st_mode
)) {
4193 fprintf(stderr
, "vtysh_connect(%s): Not a socket\n",
4199 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
4202 fprintf(stderr
, "vtysh_connect(%s): socket = %s\n", path
,
4203 safe_strerror(errno
));
4208 memset(&addr
, 0, sizeof(addr
));
4209 addr
.sun_family
= AF_UNIX
;
4210 strlcpy(addr
.sun_path
, path
, sizeof(addr
.sun_path
));
4211 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
4212 len
= addr
.sun_len
= SUN_LEN(&addr
);
4214 len
= sizeof(addr
.sun_family
) + strlen(addr
.sun_path
);
4215 #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
4217 ret
= connect(sock
, (struct sockaddr
*)&addr
, len
);
4220 fprintf(stderr
, "vtysh_connect(%s): connect = %s\n", path
,
4221 safe_strerror(errno
));
4231 static int vtysh_reconnect(struct vtysh_client
*vclient
)
4235 fprintf(stderr
, "Warning: connecting to %s...", vclient
->name
);
4236 ret
= vtysh_connect(vclient
);
4238 fprintf(stderr
, "failed!\n");
4241 fprintf(stderr
, "success!\n");
4242 if (vtysh_client_execute(vclient
, "enable") < 0)
4244 return vtysh_execute_no_pager("end");
4247 /* Return true if str ends with suffix, else return false */
4248 static int ends_with(const char *str
, const char *suffix
)
4250 if (!str
|| !suffix
)
4252 size_t lenstr
= strlen(str
);
4253 size_t lensuffix
= strlen(suffix
);
4254 if (lensuffix
> lenstr
)
4256 return strncmp(str
+ lenstr
- lensuffix
, suffix
, lensuffix
) == 0;
4259 static void vtysh_client_sorted_insert(struct vtysh_client
*head_client
,
4260 struct vtysh_client
*client
)
4262 struct vtysh_client
*prev_node
, *current_node
;
4264 prev_node
= head_client
;
4265 current_node
= head_client
->next
;
4266 while (current_node
) {
4267 if (strcmp(current_node
->path
, client
->path
) > 0)
4270 prev_node
= current_node
;
4271 current_node
= current_node
->next
;
4273 client
->next
= current_node
;
4274 prev_node
->next
= client
;
4277 #define MAXIMUM_INSTANCES 10
4279 static void vtysh_update_all_instances(struct vtysh_client
*head_client
)
4281 struct vtysh_client
*client
;
4283 struct dirent
*file
;
4286 if (head_client
->flag
!= VTYSH_OSPFD
)
4289 /* ls vty_sock_dir and look for all files ending in .vty */
4290 dir
= opendir(vtydir
);
4292 while ((file
= readdir(dir
)) != NULL
) {
4293 if (frrstr_startswith(file
->d_name
, "ospfd-")
4294 && ends_with(file
->d_name
, ".vty")) {
4295 if (n
== MAXIMUM_INSTANCES
) {
4297 "Parsing %s, client limit(%d) reached!\n",
4301 client
= (struct vtysh_client
*)malloc(
4302 sizeof(struct vtysh_client
));
4304 client
->name
= "ospfd";
4305 client
->flag
= VTYSH_OSPFD
;
4306 snprintf(client
->path
, sizeof(client
->path
),
4307 "%s/%s", vtydir
, file
->d_name
);
4308 client
->next
= NULL
;
4309 vtysh_client_sorted_insert(head_client
, client
);
4317 static int vtysh_connect_all_instances(struct vtysh_client
*head_client
)
4319 struct vtysh_client
*client
;
4322 vtysh_update_all_instances(head_client
);
4324 client
= head_client
->next
;
4326 if (vtysh_connect(client
) == 0)
4328 client
= client
->next
;
4334 int vtysh_connect_all(const char *daemon_name
)
4340 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
4342 || !strcmp(daemon_name
, vtysh_client
[i
].name
)) {
4344 if (vtysh_connect(&vtysh_client
[i
]) == 0)
4347 rc
+= vtysh_connect_all_instances(&vtysh_client
[i
]);
4351 fprintf(stderr
, "Error: no daemons match name %s!\n",
4356 /* To disable readline's filename completion. */
4357 static char *vtysh_completion_entry_function(const char *ignore
,
4363 void vtysh_readline_init(void)
4365 /* readline related settings. */
4366 char *disable_bracketed_paste
=
4367 XSTRDUP(MTYPE_TMP
, "set enable-bracketed-paste off");
4370 rl_parse_and_bind(disable_bracketed_paste
);
4371 rl_bind_key('?', (rl_command_func_t
*)vtysh_rl_describe
);
4372 rl_completion_entry_function
= vtysh_completion_entry_function
;
4373 rl_attempted_completion_function
= new_completion
;
4375 XFREE(MTYPE_TMP
, disable_bracketed_paste
);
4378 char *vtysh_prompt(void)
4380 static char buf
[512];
4382 #pragma GCC diagnostic push
4383 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
4384 /* prompt formatting has a %s in the cmd_node prompt string. */
4385 snprintf(buf
, sizeof(buf
), cmd_prompt(vty
->node
), cmd_hostname_get());
4386 #pragma GCC diagnostic pop
4390 static void vtysh_ac_line(void *arg
, const char *line
)
4394 for (i
= 0; i
< vector_active(comps
); i
++)
4395 if (!strcmp(line
, (char *)vector_slot(comps
, i
)))
4397 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, line
));
4400 static void vtysh_autocomplete(vector comps
, struct cmd_token
*token
)
4405 snprintf(accmd
, sizeof(accmd
), "autocomplete %d %s %s", token
->type
,
4406 token
->text
, token
->varname
? token
->varname
: "-");
4408 vty
->of_saved
= vty
->of
;
4410 for (i
= 0; i
< array_size(vtysh_client
); i
++)
4411 vtysh_client_run_all(&vtysh_client
[i
], accmd
, 1, vtysh_ac_line
,
4413 vty
->of
= vty
->of_saved
;
4416 static const struct cmd_variable_handler vtysh_var_handler
[] = {
4420 .completions
= vtysh_autocomplete
},
4421 {.completions
= NULL
}};
4423 void vtysh_uninit(void)
4425 if (vty
->of
!= stdout
)
4429 void vtysh_init_vty(void)
4431 struct stat st_out
, st_err
;
4433 cmd_defer_tree(true);
4435 for (size_t i
= 0; i
< array_size(vtysh_client
); i
++) {
4436 vtysh_client
[i
].fd
= -1;
4437 vtysh_client
[i
].log_fd
= -1;
4440 stderr_tty
= isatty(STDERR_FILENO
);
4442 if (fstat(STDOUT_FILENO
, &st_out
) || fstat(STDERR_FILENO
, &st_err
) ||
4443 (st_out
.st_dev
== st_err
.st_dev
&& st_out
.st_ino
== st_err
.st_ino
))
4444 stderr_stdout_same
= true;
4446 /* Make vty structure. */
4448 vty
->type
= VTY_SHELL
;
4449 vty
->node
= VIEW_NODE
;
4451 /* set default output */
4453 vtysh_pager_envdef(false);
4455 /* Initialize commands. */
4457 cmd_variable_handler_register(vtysh_var_handler
);
4461 install_node(&bgp_node
);
4462 install_element(CONFIG_NODE
, &router_bgp_cmd
);
4463 install_element(BGP_NODE
, &vtysh_exit_bgpd_cmd
);
4464 install_element(BGP_NODE
, &vtysh_quit_bgpd_cmd
);
4465 install_element(BGP_NODE
, &vtysh_end_all_cmd
);
4467 install_node(&bgp_vpnv4_node
);
4468 install_element(BGP_NODE
, &address_family_ipv4_vpn_cmd
);
4469 #ifdef KEEP_OLD_VPN_COMMANDS
4470 install_element(BGP_NODE
, &address_family_vpnv4_cmd
);
4471 #endif /* KEEP_OLD_VPN_COMMANDS */
4472 install_element(BGP_VPNV4_NODE
, &vtysh_exit_bgpd_cmd
);
4473 install_element(BGP_VPNV4_NODE
, &vtysh_quit_bgpd_cmd
);
4474 install_element(BGP_VPNV4_NODE
, &vtysh_end_all_cmd
);
4475 install_element(BGP_VPNV4_NODE
, &exit_address_family_cmd
);
4477 install_node(&bgp_vpnv6_node
);
4478 install_element(BGP_NODE
, &address_family_ipv6_vpn_cmd
);
4479 #ifdef KEEP_OLD_VPN_COMMANDS
4480 install_element(BGP_NODE
, &address_family_vpnv6_cmd
);
4481 #endif /* KEEP_OLD_VPN_COMMANDS */
4482 install_element(BGP_VPNV6_NODE
, &vtysh_exit_bgpd_cmd
);
4483 install_element(BGP_VPNV6_NODE
, &vtysh_quit_bgpd_cmd
);
4484 install_element(BGP_VPNV6_NODE
, &vtysh_end_all_cmd
);
4485 install_element(BGP_VPNV6_NODE
, &exit_address_family_cmd
);
4487 install_node(&bgp_flowspecv4_node
);
4488 install_element(BGP_NODE
, &address_family_flowspecv4_cmd
);
4489 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_exit_bgpd_cmd
);
4490 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_quit_bgpd_cmd
);
4491 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_end_all_cmd
);
4492 install_element(BGP_FLOWSPECV4_NODE
, &exit_address_family_cmd
);
4494 install_node(&bgp_flowspecv6_node
);
4495 install_element(BGP_NODE
, &address_family_flowspecv6_cmd
);
4496 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_exit_bgpd_cmd
);
4497 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_quit_bgpd_cmd
);
4498 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_end_all_cmd
);
4499 install_element(BGP_FLOWSPECV6_NODE
, &exit_address_family_cmd
);
4501 install_node(&bgp_ipv4_node
);
4502 install_element(BGP_NODE
, &address_family_ipv4_cmd
);
4503 install_element(BGP_IPV4_NODE
, &vtysh_exit_bgpd_cmd
);
4504 install_element(BGP_IPV4_NODE
, &vtysh_quit_bgpd_cmd
);
4505 install_element(BGP_IPV4_NODE
, &vtysh_end_all_cmd
);
4506 install_element(BGP_IPV4_NODE
, &exit_address_family_cmd
);
4508 install_node(&bgp_ipv4m_node
);
4509 install_element(BGP_NODE
, &address_family_ipv4_multicast_cmd
);
4510 install_element(BGP_IPV4M_NODE
, &vtysh_exit_bgpd_cmd
);
4511 install_element(BGP_IPV4M_NODE
, &vtysh_quit_bgpd_cmd
);
4512 install_element(BGP_IPV4M_NODE
, &vtysh_end_all_cmd
);
4513 install_element(BGP_IPV4M_NODE
, &exit_address_family_cmd
);
4515 install_node(&bgp_ipv4l_node
);
4516 install_element(BGP_NODE
, &address_family_ipv4_labeled_unicast_cmd
);
4517 install_element(BGP_IPV4L_NODE
, &vtysh_exit_bgpd_cmd
);
4518 install_element(BGP_IPV4L_NODE
, &vtysh_quit_bgpd_cmd
);
4519 install_element(BGP_IPV4L_NODE
, &vtysh_end_all_cmd
);
4520 install_element(BGP_IPV4L_NODE
, &exit_address_family_cmd
);
4522 install_node(&bgp_ipv6_node
);
4523 install_element(BGP_NODE
, &address_family_ipv6_cmd
);
4524 install_element(BGP_IPV6_NODE
, &vtysh_exit_bgpd_cmd
);
4525 install_element(BGP_IPV6_NODE
, &vtysh_quit_bgpd_cmd
);
4526 install_element(BGP_IPV6_NODE
, &vtysh_end_all_cmd
);
4527 install_element(BGP_IPV6_NODE
, &exit_address_family_cmd
);
4529 install_node(&bgp_ipv6m_node
);
4530 install_element(BGP_NODE
, &address_family_ipv6_multicast_cmd
);
4531 install_element(BGP_IPV6M_NODE
, &vtysh_exit_bgpd_cmd
);
4532 install_element(BGP_IPV6M_NODE
, &vtysh_quit_bgpd_cmd
);
4533 install_element(BGP_IPV6M_NODE
, &vtysh_end_all_cmd
);
4534 install_element(BGP_IPV6M_NODE
, &exit_address_family_cmd
);
4536 install_node(&bgp_ipv6l_node
);
4537 install_element(BGP_NODE
, &address_family_ipv6_labeled_unicast_cmd
);
4538 install_element(BGP_IPV6L_NODE
, &vtysh_exit_bgpd_cmd
);
4539 install_element(BGP_IPV6L_NODE
, &vtysh_quit_bgpd_cmd
);
4540 install_element(BGP_IPV6L_NODE
, &vtysh_end_all_cmd
);
4541 install_element(BGP_IPV6L_NODE
, &exit_address_family_cmd
);
4543 #if defined(ENABLE_BGP_VNC)
4544 install_node(&bgp_vrf_policy_node
);
4545 install_element(BGP_NODE
, &vnc_vrf_policy_cmd
);
4546 install_element(BGP_VRF_POLICY_NODE
, &vtysh_exit_bgpd_cmd
);
4547 install_element(BGP_VRF_POLICY_NODE
, &vtysh_quit_bgpd_cmd
);
4548 install_element(BGP_VRF_POLICY_NODE
, &vtysh_end_all_cmd
);
4549 install_element(BGP_VRF_POLICY_NODE
, &exit_vrf_policy_cmd
);
4551 install_node(&bgp_vnc_defaults_node
);
4552 install_element(BGP_NODE
, &vnc_defaults_cmd
);
4553 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_exit_bgpd_cmd
);
4554 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_quit_bgpd_cmd
);
4555 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_end_all_cmd
);
4556 install_element(BGP_VNC_DEFAULTS_NODE
, &exit_vnc_config_cmd
);
4558 install_node(&bgp_vnc_nve_group_node
);
4559 install_element(BGP_NODE
, &vnc_nve_group_cmd
);
4560 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4561 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4562 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_end_all_cmd
);
4563 install_element(BGP_VNC_NVE_GROUP_NODE
, &exit_vnc_config_cmd
);
4565 install_node(&bgp_vnc_l2_group_node
);
4566 install_element(BGP_NODE
, &vnc_l2_group_cmd
);
4567 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4568 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4569 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_end_all_cmd
);
4570 install_element(BGP_VNC_L2_GROUP_NODE
, &exit_vnc_config_cmd
);
4573 install_node(&bgp_evpn_node
);
4574 install_element(BGP_NODE
, &address_family_evpn_cmd
);
4575 install_element(BGP_EVPN_NODE
, &vtysh_quit_bgpd_cmd
);
4576 install_element(BGP_EVPN_NODE
, &vtysh_exit_bgpd_cmd
);
4577 install_element(BGP_EVPN_NODE
, &vtysh_end_all_cmd
);
4578 install_element(BGP_EVPN_NODE
, &exit_address_family_cmd
);
4580 install_node(&bgp_evpn_vni_node
);
4581 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
4582 install_element(BGP_EVPN_VNI_NODE
, &vtysh_exit_bgpd_cmd
);
4583 install_element(BGP_EVPN_VNI_NODE
, &vtysh_quit_bgpd_cmd
);
4584 install_element(BGP_EVPN_VNI_NODE
, &vtysh_end_all_cmd
);
4585 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
4587 install_node(&rpki_node
);
4588 install_element(CONFIG_NODE
, &rpki_cmd
);
4589 install_element(RPKI_NODE
, &rpki_exit_cmd
);
4590 install_element(RPKI_NODE
, &rpki_quit_cmd
);
4591 install_element(RPKI_NODE
, &vtysh_end_all_cmd
);
4593 install_node(&bmp_node
);
4594 install_element(BGP_NODE
, &bmp_targets_cmd
);
4595 install_element(BMP_NODE
, &bmp_exit_cmd
);
4596 install_element(BMP_NODE
, &bmp_quit_cmd
);
4597 install_element(BMP_NODE
, &vtysh_end_all_cmd
);
4599 install_node(&bgp_srv6_node
);
4600 install_element(BGP_NODE
, &bgp_srv6_cmd
);
4601 install_element(BGP_SRV6_NODE
, &exit_bgp_srv6_cmd
);
4602 install_element(BGP_SRV6_NODE
, &quit_bgp_srv6_cmd
);
4603 install_element(BGP_SRV6_NODE
, &vtysh_end_all_cmd
);
4604 #endif /* HAVE_BGPD */
4607 install_node(&rip_node
);
4609 install_element(CONFIG_NODE
, &router_rip_cmd
);
4610 install_element(RIP_NODE
, &vtysh_exit_ripd_cmd
);
4611 install_element(RIP_NODE
, &vtysh_quit_ripd_cmd
);
4612 install_element(RIP_NODE
, &vtysh_end_all_cmd
);
4613 #endif /* HAVE_RIPD */
4616 install_node(&ripng_node
);
4618 install_element(CONFIG_NODE
, &router_ripng_cmd
);
4619 install_element(RIPNG_NODE
, &vtysh_exit_ripngd_cmd
);
4620 install_element(RIPNG_NODE
, &vtysh_quit_ripngd_cmd
);
4621 install_element(RIPNG_NODE
, &vtysh_end_all_cmd
);
4622 #endif /* HAVE_RIPNGD */
4626 install_node(&ospf_node
);
4627 install_element(CONFIG_NODE
, &router_ospf_cmd
);
4628 install_element(OSPF_NODE
, &vtysh_exit_ospfd_cmd
);
4629 install_element(OSPF_NODE
, &vtysh_quit_ospfd_cmd
);
4630 install_element(OSPF_NODE
, &vtysh_end_all_cmd
);
4631 #endif /* HAVE_OSPFD */
4635 install_node(&ospf6_node
);
4636 install_element(CONFIG_NODE
, &router_ospf6_cmd
);
4637 install_element(OSPF6_NODE
, &vtysh_exit_ospf6d_cmd
);
4638 install_element(OSPF6_NODE
, &vtysh_quit_ospf6d_cmd
);
4639 install_element(OSPF6_NODE
, &vtysh_end_all_cmd
);
4640 #endif /* HAVE_OSPF6D */
4643 #if defined(HAVE_LDPD)
4644 install_node(&ldp_node
);
4645 install_element(CONFIG_NODE
, &ldp_mpls_ldp_cmd
);
4646 install_element(LDP_NODE
, &vtysh_exit_ldpd_cmd
);
4647 install_element(LDP_NODE
, &vtysh_quit_ldpd_cmd
);
4648 install_element(LDP_NODE
, &vtysh_end_all_cmd
);
4650 install_node(&ldp_ipv4_node
);
4651 install_element(LDP_NODE
, &ldp_address_family_ipv4_cmd
);
4652 install_element(LDP_IPV4_NODE
, &vtysh_exit_ldpd_cmd
);
4653 install_element(LDP_IPV4_NODE
, &vtysh_quit_ldpd_cmd
);
4654 install_element(LDP_IPV4_NODE
, &ldp_exit_address_family_cmd
);
4655 install_element(LDP_IPV4_NODE
, &vtysh_end_all_cmd
);
4657 install_node(&ldp_ipv6_node
);
4658 install_element(LDP_NODE
, &ldp_address_family_ipv6_cmd
);
4659 install_element(LDP_IPV6_NODE
, &vtysh_exit_ldpd_cmd
);
4660 install_element(LDP_IPV6_NODE
, &vtysh_quit_ldpd_cmd
);
4661 install_element(LDP_IPV6_NODE
, &ldp_exit_address_family_cmd
);
4662 install_element(LDP_IPV6_NODE
, &vtysh_end_all_cmd
);
4664 install_node(&ldp_ipv4_iface_node
);
4665 install_element(LDP_IPV4_NODE
, &ldp_interface_ifname_cmd
);
4666 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4667 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4668 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_end_all_cmd
);
4670 install_node(&ldp_ipv6_iface_node
);
4671 install_element(LDP_IPV6_NODE
, &ldp_interface_ifname_cmd
);
4672 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4673 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4674 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_end_all_cmd
);
4676 install_node(&ldp_l2vpn_node
);
4677 install_element(CONFIG_NODE
, &ldp_l2vpn_word_type_vpls_cmd
);
4678 install_element(LDP_L2VPN_NODE
, &vtysh_exit_ldpd_cmd
);
4679 install_element(LDP_L2VPN_NODE
, &vtysh_quit_ldpd_cmd
);
4680 install_element(LDP_L2VPN_NODE
, &vtysh_end_all_cmd
);
4682 install_node(&ldp_pseudowire_node
);
4683 install_element(LDP_L2VPN_NODE
, &ldp_member_pseudowire_ifname_cmd
);
4684 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_exit_ldpd_cmd
);
4685 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_quit_ldpd_cmd
);
4686 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_end_all_cmd
);
4691 install_node(&eigrp_node
);
4692 install_element(CONFIG_NODE
, &router_eigrp_cmd
);
4693 install_element(EIGRP_NODE
, &vtysh_exit_eigrpd_cmd
);
4694 install_element(EIGRP_NODE
, &vtysh_quit_eigrpd_cmd
);
4695 install_element(EIGRP_NODE
, &vtysh_end_all_cmd
);
4696 #endif /* HAVE_EIGRPD */
4700 install_node(&babel_node
);
4701 install_element(CONFIG_NODE
, &router_babel_cmd
);
4702 install_element(BABEL_NODE
, &vtysh_exit_babeld_cmd
);
4703 install_element(BABEL_NODE
, &vtysh_quit_babeld_cmd
);
4704 install_element(BABEL_NODE
, &vtysh_end_all_cmd
);
4705 #endif /* HAVE_BABELD */
4709 install_node(&isis_node
);
4710 install_element(CONFIG_NODE
, &router_isis_cmd
);
4711 install_element(ISIS_NODE
, &vtysh_exit_isisd_cmd
);
4712 install_element(ISIS_NODE
, &vtysh_quit_isisd_cmd
);
4713 install_element(ISIS_NODE
, &vtysh_end_all_cmd
);
4714 #endif /* HAVE_ISISD */
4718 install_node(&openfabric_node
);
4719 install_element(CONFIG_NODE
, &router_openfabric_cmd
);
4720 install_element(OPENFABRIC_NODE
, &vtysh_exit_fabricd_cmd
);
4721 install_element(OPENFABRIC_NODE
, &vtysh_quit_fabricd_cmd
);
4722 install_element(OPENFABRIC_NODE
, &vtysh_end_all_cmd
);
4723 #endif /* HAVE_FABRICD */
4727 install_node(&pbr_map_node
);
4728 install_element(CONFIG_NODE
, &vtysh_pbr_map_cmd
);
4729 install_element(CONFIG_NODE
, &vtysh_no_pbr_map_cmd
);
4730 install_element(PBRMAP_NODE
, &vtysh_exit_pbr_map_cmd
);
4731 install_element(PBRMAP_NODE
, &vtysh_quit_pbr_map_cmd
);
4732 install_element(PBRMAP_NODE
, &vtysh_end_all_cmd
);
4733 #endif /* HAVE_PBRD */
4737 install_node(&bfd_node
);
4738 install_element(CONFIG_NODE
, &bfd_enter_cmd
);
4739 install_element(BFD_NODE
, &vtysh_exit_bfdd_cmd
);
4740 install_element(BFD_NODE
, &vtysh_quit_bfdd_cmd
);
4741 install_element(BFD_NODE
, &vtysh_end_all_cmd
);
4743 install_node(&bfd_peer_node
);
4744 install_element(BFD_NODE
, &bfd_peer_enter_cmd
);
4745 install_element(BFD_PEER_NODE
, &vtysh_exit_bfdd_cmd
);
4746 install_element(BFD_PEER_NODE
, &vtysh_quit_bfdd_cmd
);
4747 install_element(BFD_PEER_NODE
, &vtysh_end_all_cmd
);
4749 install_node(&bfd_profile_node
);
4750 install_element(BFD_NODE
, &bfd_profile_enter_cmd
);
4751 install_element(BFD_PROFILE_NODE
, &vtysh_exit_bfdd_cmd
);
4752 install_element(BFD_PROFILE_NODE
, &vtysh_quit_bfdd_cmd
);
4753 install_element(BFD_PROFILE_NODE
, &vtysh_end_all_cmd
);
4754 #endif /* HAVE_BFDD */
4756 install_node(&segment_routing_node
);
4757 install_element(CONFIG_NODE
, &segment_routing_cmd
);
4758 install_element(SEGMENT_ROUTING_NODE
, &vtysh_exit_sr_cmd
);
4759 install_element(SEGMENT_ROUTING_NODE
, &vtysh_quit_sr_cmd
);
4760 install_element(SEGMENT_ROUTING_NODE
, &vtysh_end_all_cmd
);
4762 #if defined(HAVE_PATHD)
4763 install_node(&sr_traffic_eng_node
);
4764 install_node(&srte_segment_list_node
);
4765 install_node(&srte_policy_node
);
4766 install_node(&srte_candidate_dyn_node
);
4768 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_exit_pathd_cmd
);
4769 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_quit_pathd_cmd
);
4770 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_exit_pathd_cmd
);
4771 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_quit_pathd_cmd
);
4772 install_element(SR_POLICY_NODE
, &vtysh_exit_pathd_cmd
);
4773 install_element(SR_POLICY_NODE
, &vtysh_quit_pathd_cmd
);
4774 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_exit_pathd_cmd
);
4775 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_quit_pathd_cmd
);
4778 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_end_all_cmd
);
4779 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_end_all_cmd
);
4780 install_element(SR_POLICY_NODE
, &vtysh_end_all_cmd
);
4781 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_end_all_cmd
);
4783 install_element(SEGMENT_ROUTING_NODE
, &sr_traffic_eng_cmd
);
4784 install_element(SR_TRAFFIC_ENG_NODE
, &srte_segment_list_cmd
);
4785 install_element(SR_TRAFFIC_ENG_NODE
, &srte_policy_cmd
);
4786 install_element(SR_POLICY_NODE
, &srte_policy_candidate_dyn_path_cmd
);
4788 install_node(&pcep_node
);
4789 install_node(&pcep_pcc_node
);
4790 install_node(&pcep_pce_node
);
4791 install_node(&pcep_pce_config_node
);
4793 install_element(PCEP_NODE
, &vtysh_exit_pathd_cmd
);
4794 install_element(PCEP_NODE
, &vtysh_quit_pathd_cmd
);
4795 install_element(PCEP_PCC_NODE
, &vtysh_exit_pathd_cmd
);
4796 install_element(PCEP_PCC_NODE
, &vtysh_quit_pathd_cmd
);
4797 install_element(PCEP_PCE_NODE
, &vtysh_exit_pathd_cmd
);
4798 install_element(PCEP_PCE_NODE
, &vtysh_quit_pathd_cmd
);
4799 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_exit_pathd_cmd
);
4800 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_quit_pathd_cmd
);
4802 install_element(PCEP_NODE
, &vtysh_end_all_cmd
);
4803 install_element(PCEP_PCC_NODE
, &vtysh_end_all_cmd
);
4804 install_element(PCEP_PCE_NODE
, &vtysh_end_all_cmd
);
4805 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_end_all_cmd
);
4807 install_element(SR_TRAFFIC_ENG_NODE
, &pcep_cmd
);
4808 install_element(PCEP_NODE
, &pcep_cli_pcc_cmd
);
4809 install_element(PCEP_NODE
, &pcep_cli_pcep_pce_config_cmd
);
4810 install_element(PCEP_NODE
, &pcep_cli_pce_cmd
);
4812 #endif /* HAVE_PATHD */
4815 install_node(&keychain_node
);
4816 install_element(CONFIG_NODE
, &key_chain_cmd
);
4817 install_element(KEYCHAIN_NODE
, &key_chain_cmd
);
4818 install_element(KEYCHAIN_NODE
, &vtysh_exit_keys_cmd
);
4819 install_element(KEYCHAIN_NODE
, &vtysh_quit_keys_cmd
);
4820 install_element(KEYCHAIN_NODE
, &vtysh_end_all_cmd
);
4822 install_node(&keychain_key_node
);
4823 install_element(KEYCHAIN_NODE
, &key_cmd
);
4824 install_element(KEYCHAIN_KEY_NODE
, &key_chain_cmd
);
4825 install_element(KEYCHAIN_KEY_NODE
, &vtysh_exit_keys_cmd
);
4826 install_element(KEYCHAIN_KEY_NODE
, &vtysh_quit_keys_cmd
);
4827 install_element(KEYCHAIN_KEY_NODE
, &vtysh_end_all_cmd
);
4830 install_node(&nh_group_node
);
4831 install_element(CONFIG_NODE
, &vtysh_nexthop_group_cmd
);
4832 install_element(CONFIG_NODE
, &vtysh_no_nexthop_group_cmd
);
4833 install_element(NH_GROUP_NODE
, &vtysh_end_all_cmd
);
4834 install_element(NH_GROUP_NODE
, &vtysh_exit_nexthop_group_cmd
);
4835 install_element(NH_GROUP_NODE
, &vtysh_quit_nexthop_group_cmd
);
4838 install_node(&zebra_node
);
4840 install_node(&interface_node
);
4841 install_element(CONFIG_NODE
, &vtysh_interface_cmd
);
4842 install_element(INTERFACE_NODE
, &vtysh_end_all_cmd
);
4843 install_element(INTERFACE_NODE
, &vtysh_exit_interface_cmd
);
4844 install_element(INTERFACE_NODE
, &vtysh_quit_interface_cmd
);
4846 install_node(&link_params_node
);
4847 install_element(INTERFACE_NODE
, &vtysh_link_params_cmd
);
4848 install_element(LINK_PARAMS_NODE
, &exit_link_params_cmd
);
4849 install_element(LINK_PARAMS_NODE
, &vtysh_end_all_cmd
);
4850 install_element(LINK_PARAMS_NODE
, &vtysh_exit_link_params_cmd
);
4851 install_element(LINK_PARAMS_NODE
, &vtysh_quit_link_params_cmd
);
4853 install_node(&pw_node
);
4854 install_element(CONFIG_NODE
, &vtysh_pseudowire_cmd
);
4855 install_element(PW_NODE
, &vtysh_end_all_cmd
);
4856 install_element(PW_NODE
, &vtysh_exit_pseudowire_cmd
);
4857 install_element(PW_NODE
, &vtysh_quit_pseudowire_cmd
);
4859 install_node(&vrf_node
);
4860 install_element(CONFIG_NODE
, &vtysh_vrf_cmd
);
4861 install_element(VRF_NODE
, &exit_vrf_config_cmd
);
4862 install_element(VRF_NODE
, &vtysh_end_all_cmd
);
4863 install_element(VRF_NODE
, &vtysh_exit_vrf_cmd
);
4864 install_element(VRF_NODE
, &vtysh_quit_vrf_cmd
);
4866 install_element(CONFIG_NODE
, &vtysh_affinity_map_cmd
);
4867 install_element(CONFIG_NODE
, &vtysh_no_affinity_map_cmd
);
4869 install_node(&rmap_node
);
4870 install_element(CONFIG_NODE
, &vtysh_route_map_cmd
);
4871 install_element(RMAP_NODE
, &vtysh_exit_rmap_cmd
);
4872 install_element(RMAP_NODE
, &vtysh_quit_rmap_cmd
);
4873 install_element(RMAP_NODE
, &vtysh_end_all_cmd
);
4875 install_node(&vty_node
);
4876 install_element(CONFIG_NODE
, &vtysh_line_vty_cmd
);
4877 install_element(VTY_NODE
, &vtysh_exit_line_vty_cmd
);
4878 install_element(VTY_NODE
, &vtysh_quit_line_vty_cmd
);
4879 install_element(VTY_NODE
, &vtysh_end_all_cmd
);
4882 struct cmd_node
*node
;
4883 for (unsigned int i
= 0; i
< vector_active(cmdvec
); i
++) {
4884 node
= vector_slot(cmdvec
, i
);
4885 if (!node
|| node
->node
== VIEW_NODE
)
4887 vtysh_install_default(node
->node
);
4893 install_element(VIEW_NODE
, &vtysh_enable_cmd
);
4894 install_element(ENABLE_NODE
, &vtysh_config_terminal_cmd
);
4895 install_element(ENABLE_NODE
, &vtysh_disable_cmd
);
4897 /* "exit" command. */
4898 install_element(VIEW_NODE
, &vtysh_exit_all_cmd
);
4899 install_element(CONFIG_NODE
, &vtysh_exit_all_cmd
);
4900 install_element(VIEW_NODE
, &vtysh_quit_all_cmd
);
4901 install_element(CONFIG_NODE
, &vtysh_quit_all_cmd
);
4903 /* "end" command. */
4904 install_element(CONFIG_NODE
, &vtysh_end_all_cmd
);
4905 install_element(ENABLE_NODE
, &vtysh_end_all_cmd
);
4907 /* SRv6 Data-plane */
4908 install_node(&srv6_node
);
4909 install_element(SEGMENT_ROUTING_NODE
, &srv6_cmd
);
4910 install_element(SRV6_NODE
, &srv6_locators_cmd
);
4911 install_element(SRV6_NODE
, &exit_srv6_config_cmd
);
4912 install_element(SRV6_NODE
, &vtysh_end_all_cmd
);
4914 install_node(&srv6_locs_node
);
4915 install_element(SRV6_LOCS_NODE
, &srv6_locator_cmd
);
4916 install_element(SRV6_LOCS_NODE
, &exit_srv6_locs_config_cmd
);
4917 install_element(SRV6_LOCS_NODE
, &vtysh_end_all_cmd
);
4919 install_node(&srv6_loc_node
);
4920 install_element(SRV6_LOC_NODE
, &exit_srv6_loc_config_cmd
);
4921 install_element(SRV6_LOC_NODE
, &vtysh_end_all_cmd
);
4923 install_element(ENABLE_NODE
, &vtysh_show_running_config_cmd
);
4924 install_element(ENABLE_NODE
, &vtysh_copy_running_config_cmd
);
4925 install_element(ENABLE_NODE
, &vtysh_copy_to_running_cmd
);
4927 /* "write terminal" command. */
4928 install_element(ENABLE_NODE
, &vtysh_write_terminal_cmd
);
4930 install_element(CONFIG_NODE
, &vtysh_integrated_config_cmd
);
4931 install_element(CONFIG_NODE
, &no_vtysh_integrated_config_cmd
);
4933 /* "write memory" command. */
4934 install_element(ENABLE_NODE
, &vtysh_write_memory_cmd
);
4936 install_element(CONFIG_NODE
, &start_config_cmd
);
4937 install_element(CONFIG_NODE
, &end_config_cmd
);
4939 install_element(CONFIG_NODE
, &vtysh_terminal_paginate_cmd
);
4940 install_element(VIEW_NODE
, &vtysh_terminal_paginate_cmd
);
4941 install_element(VIEW_NODE
, &vtysh_terminal_length_cmd
);
4942 install_element(VIEW_NODE
, &vtysh_terminal_no_length_cmd
);
4943 install_element(VIEW_NODE
, &vtysh_show_daemons_cmd
);
4945 install_element(VIEW_NODE
, &vtysh_terminal_monitor_cmd
);
4946 install_element(VIEW_NODE
, &no_vtysh_terminal_monitor_cmd
);
4948 install_element(VIEW_NODE
, &vtysh_ping_cmd
);
4949 install_element(VIEW_NODE
, &vtysh_motd_cmd
);
4950 install_element(VIEW_NODE
, &vtysh_ping_ip_cmd
);
4951 install_element(VIEW_NODE
, &vtysh_traceroute_cmd
);
4952 install_element(VIEW_NODE
, &vtysh_traceroute_ip_cmd
);
4953 install_element(VIEW_NODE
, &vtysh_mtrace_cmd
);
4954 install_element(VIEW_NODE
, &vtysh_ping6_cmd
);
4955 install_element(VIEW_NODE
, &vtysh_traceroute6_cmd
);
4956 #if defined(HAVE_SHELL_ACCESS)
4957 install_element(VIEW_NODE
, &vtysh_telnet_cmd
);
4958 install_element(VIEW_NODE
, &vtysh_telnet_port_cmd
);
4959 install_element(VIEW_NODE
, &vtysh_ssh_cmd
);
4961 #if defined(HAVE_SHELL_ACCESS)
4962 install_element(ENABLE_NODE
, &vtysh_start_shell_cmd
);
4963 install_element(ENABLE_NODE
, &vtysh_start_bash_cmd
);
4964 install_element(ENABLE_NODE
, &vtysh_start_zsh_cmd
);
4968 install_element(VIEW_NODE
, &vtysh_show_error_code_cmd
);
4969 install_element(ENABLE_NODE
, &vtysh_show_debugging_cmd
);
4970 install_element(ENABLE_NODE
, &vtysh_show_debugging_hashtable_cmd
);
4971 install_element(ENABLE_NODE
, &vtysh_debug_all_cmd
);
4972 install_element(CONFIG_NODE
, &vtysh_debug_all_cmd
);
4973 install_element(ENABLE_NODE
, &vtysh_debug_memstats_cmd
);
4974 install_element(CONFIG_NODE
, &vtysh_debug_memstats_cmd
);
4975 install_element(ENABLE_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4976 install_element(CONFIG_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4979 install_element(ENABLE_NODE
, &show_config_running_cmd
);
4980 install_element(ENABLE_NODE
, &show_yang_operational_data_cmd
);
4981 install_element(ENABLE_NODE
, &show_yang_module_cmd
);
4982 install_element(ENABLE_NODE
, &show_yang_module_detail_cmd
);
4983 install_element(ENABLE_NODE
, &debug_nb_cmd
);
4984 install_element(CONFIG_NODE
, &debug_nb_cmd
);
4986 /* misc lib show commands */
4987 install_element(VIEW_NODE
, &vtysh_show_history_cmd
);
4988 install_element(VIEW_NODE
, &vtysh_show_memory_cmd
);
4989 install_element(VIEW_NODE
, &vtysh_show_modules_cmd
);
4990 install_element(VIEW_NODE
, &vtysh_show_work_queues_cmd
);
4991 install_element(VIEW_NODE
, &vtysh_show_work_queues_daemon_cmd
);
4992 install_element(VIEW_NODE
, &vtysh_show_thread_cmd
);
4993 install_element(VIEW_NODE
, &vtysh_show_poll_cmd
);
4994 install_element(VIEW_NODE
, &vtysh_show_thread_timer_cmd
);
4997 install_element(VIEW_NODE
, &vtysh_show_logging_cmd
);
4999 install_element(CONFIG_NODE
, &vtysh_service_password_encrypt_cmd
);
5000 install_element(CONFIG_NODE
, &no_vtysh_service_password_encrypt_cmd
);
5002 install_element(CONFIG_NODE
, &vtysh_allow_reserved_ranges_cmd
);
5003 install_element(CONFIG_NODE
, &no_vtysh_allow_reserved_ranges_cmd
);
5005 install_element(CONFIG_NODE
, &vtysh_password_cmd
);
5006 install_element(CONFIG_NODE
, &no_vtysh_password_cmd
);
5007 install_element(CONFIG_NODE
, &vtysh_enable_password_cmd
);
5008 install_element(CONFIG_NODE
, &no_vtysh_enable_password_cmd
);