1 /* Virtual terminal interface shell.
2 * Copyright (C) 2000 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <sys/resource.h>
29 /* readline carries some ancient definitions around */
30 #pragma GCC diagnostic push
31 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
32 #include <readline/readline.h>
33 #include <readline/history.h>
34 #pragma GCC diagnostic pop
45 #include "vtysh/vtysh.h"
46 #include "vtysh/vtysh_daemons.h"
50 #include "command_graph.h"
55 DEFINE_MTYPE_STATIC(MVTYSH
, VTYSH_CMD
, "Vtysh cmd copy");
60 /* VTY shell pager name. */
61 char *vtysh_pager_name
= NULL
;
63 /* VTY should add timestamp */
64 bool vtysh_add_timestamp
;
66 /* VTY shell client structure */
71 char path
[MAXPATHLEN
];
72 struct vtysh_client
*next
;
74 struct thread
*log_reader
;
78 static bool stderr_tty
;
79 static bool stderr_stdout_same
;
81 /* Some utility functions for working on vtysh-specific vty tasks */
83 static FILE *vty_open_pager(struct vty
*vty
)
88 if (!vtysh_pager_name
)
91 vty
->of_saved
= vty
->of
;
92 vty
->of
= popen(vtysh_pager_name
, "w");
93 if (vty
->of
== NULL
) {
94 vty
->of
= vty
->of_saved
;
104 static int vty_close_pager(struct vty
*vty
)
110 if (pclose(vty
->of
) == -1) {
115 vty
->of
= vty
->of_saved
;
116 vty
->is_paged
= false;
121 static void vtysh_pager_envdef(bool fallback
)
125 pager_defined
= getenv("VTYSH_PAGER");
128 vtysh_pager_name
= strdup(pager_defined
);
130 vtysh_pager_name
= strdup(VTYSH_PAGER
);
135 struct vtysh_client vtysh_client
[] = {
136 {.name
= "zebra", .flag
= VTYSH_ZEBRA
},
137 {.name
= "ripd", .flag
= VTYSH_RIPD
},
138 {.name
= "ripngd", .flag
= VTYSH_RIPNGD
},
139 {.name
= "ospfd", .flag
= VTYSH_OSPFD
},
140 {.name
= "ospf6d", .flag
= VTYSH_OSPF6D
},
141 {.name
= "ldpd", .flag
= VTYSH_LDPD
},
142 {.name
= "bgpd", .flag
= VTYSH_BGPD
},
143 {.name
= "isisd", .flag
= VTYSH_ISISD
},
144 {.name
= "pimd", .flag
= VTYSH_PIMD
},
145 {.name
= "nhrpd", .flag
= VTYSH_NHRPD
},
146 {.name
= "eigrpd", .flag
= VTYSH_EIGRPD
},
147 {.name
= "babeld", .flag
= VTYSH_BABELD
},
148 {.name
= "sharpd", .flag
= VTYSH_SHARPD
},
149 {.name
= "fabricd", .flag
= VTYSH_FABRICD
},
150 {.name
= "watchfrr", .flag
= VTYSH_WATCHFRR
},
151 {.name
= "pbrd", .flag
= VTYSH_PBRD
},
152 {.name
= "staticd", .flag
= VTYSH_STATICD
},
153 {.name
= "bfdd", .flag
= VTYSH_BFDD
},
154 {.name
= "vrrpd", .flag
= VTYSH_VRRPD
},
155 {.name
= "pathd", .flag
= VTYSH_PATHD
},
156 {.name
= "pim6d", .flag
= VTYSH_PIM6D
},
159 /* Searches for client by name, returns index */
160 static int vtysh_client_lookup(const char *name
)
164 for (unsigned int i
= 0; i
< array_size(vtysh_client
); i
++) {
165 if (strmatch(vtysh_client
[i
].name
, name
)) {
174 enum vtysh_write_integrated vtysh_write_integrated
=
175 WRITE_INTEGRATED_UNSPECIFIED
;
177 static int vtysh_reconnect(struct vtysh_client
*vclient
);
179 static void vclient_close(struct vtysh_client
*vclient
)
181 if (vclient
->fd
>= 0) {
184 "Warning: closing connection to %s because of an I/O error!\n",
187 /* indicate as candidate for reconnect */
188 vclient
->fd
= VTYSH_WAS_ACTIVE
;
192 static ssize_t
vtysh_client_receive(struct vtysh_client
*vclient
, char *buf
,
193 size_t bufsz
, int *pass_fd
)
195 struct iovec iov
[1] = {
202 uint8_t buf
[CMSG_SPACE(sizeof(int))];
203 struct cmsghdr align
;
207 .msg_iovlen
= array_size(iov
),
208 .msg_control
= u
.buf
,
209 .msg_controllen
= sizeof(u
.buf
),
211 struct cmsghdr
*cmh
= CMSG_FIRSTHDR(&mh
);
214 cmh
->cmsg_level
= SOL_SOCKET
;
215 cmh
->cmsg_type
= SCM_RIGHTS
;
216 cmh
->cmsg_len
= CMSG_LEN(sizeof(int));
217 memset(CMSG_DATA(cmh
), -1, sizeof(int));
220 ret
= recvmsg(vclient
->fd
, &mh
, 0);
221 if (ret
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
225 if (cmh
->cmsg_len
== CMSG_LEN(sizeof(int))) {
228 memcpy(&fd
, CMSG_DATA(cmh
), sizeof(int));
240 * Send a CLI command to a client and read the response.
242 * Output will be printed to vty->of. If you want to suppress output, set that
246 * the client to send the command to
249 * the command to send
252 * if non-null, this will be called with each line of output received from
253 * the client passed in the second parameter
256 * optional first argument to pass to callback
261 static int vtysh_client_run(struct vtysh_client
*vclient
, const char *line
,
262 void (*callback
)(void *, const char *), void *cbarg
,
267 char *buf
= stackbuf
;
268 size_t bufsz
= sizeof(stackbuf
);
269 char *bufvalid
, *end
= NULL
;
270 char terminator
[3] = {0, 0, 0};
272 /* vclinet was previously active, try to reconnect */
273 if (vclient
->fd
== VTYSH_WAS_ACTIVE
) {
274 ret
= vtysh_reconnect(vclient
);
282 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
284 /* close connection and try to reconnect */
285 vclient_close(vclient
);
286 ret
= vtysh_reconnect(vclient
);
290 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
299 nread
= vtysh_client_receive(
300 vclient
, bufvalid
, buf
+ bufsz
- bufvalid
- 1, pass_fd
);
302 if (nread
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
308 "vtysh: error reading from %s: %s (%d)",
309 vclient
->name
, safe_strerror(errno
),
316 /* Null terminate so we may pass this to *printf later. */
320 * We expect string output from daemons, so instead of looking
321 * for the full 3 null bytes of the terminator, we check for
322 * just one instead and assume it is the first byte of the
323 * terminator. The presence of the full terminator is checked
326 if (bufvalid
- buf
>= 4)
327 end
= memmem(bufvalid
- 4, 4, "\0", 1);
330 * calculate # bytes we have, up to & not including the
331 * terminator if present
333 size_t textlen
= (end
? end
: bufvalid
) - buf
;
336 /* feed line processing callback if present */
337 while (callback
&& bufvalid
> buf
&& (end
> buf
|| !end
)) {
338 textlen
= (end
? end
: bufvalid
) - buf
;
339 char *eol
= memchr(buf
, '\n', textlen
);
345 * no line break, end of input, no text left
346 * before end; nothing to write
350 /* no nl, end of input, but some text left */
352 else if (bufvalid
== buf
+ bufsz
- 1) {
354 * no nl, no end of input, no buffer space;
360 if (buf
== stackbuf
) {
361 new = XMALLOC(MTYPE_TMP
, bufsz
);
362 memcpy(new, stackbuf
, sizeof(stackbuf
));
364 new = XREALLOC(MTYPE_TMP
, buf
, bufsz
);
366 bufvalid
= bufvalid
- buf
+ new;
368 /* if end != NULL, we won't be reading more
378 /* eol is at line end now, either \n => \0 or \0\0\0 */
379 assert(eol
&& eol
<= bufvalid
);
382 vty_out(vty
, "%s\n", buf
);
384 callback(cbarg
, buf
);
386 /* shift back data and adjust bufvalid */
387 memmove(buf
, eol
, bufvalid
- eol
);
388 bufvalid
-= eol
- buf
;
393 /* else if no callback, dump raw */
396 vty_out(vty
, "%s", buf
);
397 memmove(buf
, buf
+ textlen
, bufvalid
- buf
- textlen
);
403 * ----------------------------------------------------
404 * At this point `buf` should be in one of two states:
405 * - Empty (i.e. buf == bufvalid)
406 * - Contains up to 4 bytes of the terminator
407 * ----------------------------------------------------
409 assert(((buf
== bufvalid
)
410 || (bufvalid
- buf
<= 4 && buf
[0] == 0x00)));
413 /* if we have the terminator, break */
414 if (end
&& bufvalid
- buf
== 4) {
415 assert(!memcmp(buf
, terminator
, 3));
424 vclient_close(vclient
);
428 XFREE(MTYPE_TMP
, buf
);
432 static int vtysh_client_run_all(struct vtysh_client
*head_client
,
433 const char *line
, int continue_on_err
,
434 void (*callback
)(void *, const char *),
437 struct vtysh_client
*client
;
438 int rc
, rc_all
= CMD_SUCCESS
;
439 int correct_instance
= 0, wrong_instance
= 0;
441 for (client
= head_client
; client
; client
= client
->next
) {
442 rc
= vtysh_client_run(client
, line
, callback
, cbarg
, NULL
);
443 if (rc
== CMD_NOT_MY_INSTANCE
) {
449 if (rc
!= CMD_SUCCESS
) {
450 if (!continue_on_err
)
455 if (wrong_instance
&& !correct_instance
&& vty
->of
) {
457 "%% [%s]: command ignored as it targets an instance that is not running\n",
459 rc_all
= CMD_WARNING_CONFIG_FAILED
;
465 * Execute command against all daemons.
468 * where to start walking in the daemon list
471 * the specific command to execute
476 static int vtysh_client_execute(struct vtysh_client
*head_client
,
479 return vtysh_client_run_all(head_client
, line
, 0, NULL
, NULL
);
482 /* Execute by name */
483 static int vtysh_client_execute_name(const char *name
, const char *line
)
485 int ret
= CMD_SUCCESS
;
488 idx_client
= vtysh_client_lookup(name
);
489 if (idx_client
!= -1)
490 ret
= vtysh_client_execute(&vtysh_client
[idx_client
], line
);
492 vty_out(vty
, "Client not found\n");
500 * Retrieve all running config from daemons and parse it with the vtysh config
501 * parser. Returned output is not displayed to the user.
504 * where to start walking in the daemon list
507 * the specific command to execute
509 static void vtysh_client_config(struct vtysh_client
*head_client
, char *line
)
511 /* watchfrr currently doesn't load any config, and has some hardcoded
512 * settings that show up in "show run". skip it here (for now at
513 * least) so we don't get that mangled up in config-write.
515 if (head_client
->flag
== VTYSH_WATCHFRR
)
518 /* suppress output to user */
519 vty
->of_saved
= vty
->of
;
521 vtysh_client_run_all(head_client
, line
, 1, vtysh_config_parse_line
,
523 vty
->of
= vty
->of_saved
;
526 /* Command execution over the vty interface. */
527 static int vtysh_execute_func(const char *line
, int pager
)
532 const struct cmd_element
*cmd
;
534 int saved_ret
, saved_node
;
536 /* Split readline string up into the vector. */
537 vline
= cmd_make_strvec(line
);
542 if (vtysh_add_timestamp
&& strncmp(line
, "exit", 4)) {
545 (void)frr_timestamp(3, ts
, sizeof(ts
));
546 vty_out(vty
, "%% %s\n\n", ts
);
549 saved_ret
= ret
= cmd_execute(vty
, line
, &cmd
, 1);
550 saved_node
= vty
->node
;
553 * If command doesn't succeeded in current node, try to walk up in node
554 * tree. Changing vty->node is enough to try it just out without actual
555 * walkup in the vtysh.
557 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
558 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
559 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
560 && vty
->node
> CONFIG_NODE
) {
561 vty
->node
= node_parent(vty
->node
);
562 ret
= cmd_execute(vty
, line
, &cmd
, 1);
566 vty
->node
= saved_node
;
569 * If command succeeded in any other node than current (tried > 0) we
570 * have to move into node in the vtysh where it succeeded.
572 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
573 || ret
== CMD_WARNING
) {
575 vtysh_execute("exit");
578 * If command didn't succeed in any node, continue with return value
585 cmd_free_strvec(vline
);
590 case CMD_WARNING_CONFIG_FAILED
:
591 if (vty
->type
== VTY_FILE
)
592 vty_out(vty
, "Warning...\n");
594 case CMD_ERR_AMBIGUOUS
:
595 vty_out(vty
, "%% Ambiguous command: %s\n", line
);
597 case CMD_ERR_NO_MATCH
:
598 vty_out(vty
, "%% Unknown command: %s\n", line
);
600 case CMD_ERR_INCOMPLETE
:
601 vty_out(vty
, "%% Command incomplete: %s\n", line
);
603 case CMD_SUCCESS_DAEMON
: {
605 * FIXME: Don't open pager for exit commands. popen() causes
606 * problems if exited from vtysh at all. This hack shouldn't
607 * cause any problem but is really ugly.
609 if (pager
&& strncmp(line
, "exit", 4))
612 if (!strcmp(cmd
->string
, "configure")) {
613 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
614 cmd_stat
= vtysh_client_execute(
615 &vtysh_client
[i
], line
);
616 if (cmd_stat
== CMD_WARNING
)
622 vline
= cmd_make_strvec(line
);
627 vty_close_pager(vty
);
631 ret
= cmd_execute_command(vline
, vty
, &cmd
, 1);
632 cmd_free_strvec(vline
);
633 if (ret
!= CMD_SUCCESS_DAEMON
)
635 } else if (cmd
->func
) {
636 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
641 cmd_stat
= CMD_SUCCESS
;
642 struct vtysh_client
*vc
;
643 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
644 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
645 if (vtysh_client
[i
].fd
< 0
646 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
647 for (vc
= &vtysh_client
[i
]; vc
;
649 if (vc
->fd
== VTYSH_WAS_ACTIVE
)
652 if (vtysh_client
[i
].fd
< 0
653 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
654 bool any_inst
= false;
655 for (vc
= &vtysh_client
[i
]; vc
;
661 "%s is not running\n",
662 vtysh_client
[i
].name
);
663 cmd_stat
= CMD_ERR_NO_DAEMON
;
667 cmd_stat
= vtysh_client_execute(
668 &vtysh_client
[i
], line
);
669 if (cmd_stat
!= CMD_SUCCESS
)
673 if (cmd_stat
!= CMD_SUCCESS
&& cmd_stat
!= CMD_ERR_NO_DAEMON
)
677 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
681 vty_close_pager(vty
);
686 int vtysh_execute_no_pager(const char *line
)
688 return vtysh_execute_func(line
, 0);
691 int vtysh_execute(const char *line
)
693 return vtysh_execute_func(line
, 1);
696 static char *trim(char *s
)
707 while (end
>= s
&& isspace((unsigned char)*end
))
711 while (*s
&& isspace((unsigned char)*s
))
717 int vtysh_mark_file(const char *filename
)
724 const struct cmd_element
*cmd
;
725 int saved_ret
, prev_node
;
727 char *vty_buf_copy
= NULL
;
728 char *vty_buf_trimmed
= NULL
;
730 if (strncmp("-", filename
, 1) == 0)
733 confp
= fopen(filename
, "r");
736 fprintf(stderr
, "%% Can't open config file %s due to '%s'.\n",
737 filename
, safe_strerror(errno
));
738 return CMD_ERR_NO_FILE
;
742 vty
->wfd
= STDOUT_FILENO
;
743 vty
->type
= VTY_TERM
;
744 vty
->node
= CONFIG_NODE
;
746 vtysh_execute_no_pager("enable");
747 vtysh_execute_no_pager("configure");
748 vty_buf_copy
= XCALLOC(MTYPE_VTYSH_CMD
, VTY_BUFSIZ
);
750 while (fgets(vty
->buf
, VTY_BUFSIZ
, confp
)) {
753 strlcpy(vty_buf_copy
, vty
->buf
, VTY_BUFSIZ
);
754 vty_buf_trimmed
= trim(vty_buf_copy
);
756 if (vty_buf_trimmed
[0] == '!' || vty_buf_trimmed
[0] == '#') {
757 vty_out(vty
, "%s", vty
->buf
);
761 /* Split readline string up into the vector. */
762 vline
= cmd_make_strvec(vty
->buf
);
765 vty_out(vty
, "%s", vty
->buf
);
770 * Ignore the "end" lines, we will generate these where
773 if (strlen(vty_buf_trimmed
) == 3
774 && strncmp("end", vty_buf_trimmed
, 3) == 0) {
775 cmd_free_strvec(vline
);
779 prev_node
= vty
->node
;
780 saved_ret
= ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
783 * If command doesn't succeeded in current node, try to walk up
784 * in node tree. Changing vty->node is enough to try it just
785 * out without actual walkup in the vtysh.
787 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
788 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
789 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
790 && vty
->node
> CONFIG_NODE
) {
791 vty
->node
= node_parent(vty
->node
);
792 ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
797 * If command succeeded in any other node than current (tried >
798 * 0) we have to move into node in the vtysh where it
801 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
802 || ret
== CMD_WARNING
) {
804 vty_out(vty
, "exit\n");
807 * If command didn't succeed in any node, continue with return
808 * value from first try.
812 vty
->node
= prev_node
;
815 cmd_free_strvec(vline
);
818 case CMD_WARNING_CONFIG_FAILED
:
819 if (vty
->type
== VTY_FILE
)
820 fprintf(stderr
, "line %d: Warning...: %s\n",
824 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
826 case CMD_ERR_AMBIGUOUS
:
827 fprintf(stderr
, "line %d: %% Ambiguous command: %s\n",
831 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
832 return CMD_ERR_AMBIGUOUS
;
833 case CMD_ERR_NO_MATCH
:
834 fprintf(stderr
, "line %d: %% Unknown command: %s\n",
838 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
839 return CMD_ERR_NO_MATCH
;
840 case CMD_ERR_INCOMPLETE
:
841 fprintf(stderr
, "line %d: %% Command incomplete: %s\n",
845 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
846 return CMD_ERR_INCOMPLETE
;
848 vty_out(vty
, "%s", vty
->buf
);
849 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
850 vty_out(vty
, "end\n");
852 case CMD_SUCCESS_DAEMON
: {
855 vty_out(vty
, "%s", vty
->buf
);
856 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
857 vty_out(vty
, "end\n");
858 cmd_stat
= vtysh_client_execute(&vtysh_client
[0],
860 if (cmd_stat
!= CMD_SUCCESS
)
864 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
868 /* This is the end */
869 vty_out(vty
, "\nend\n");
871 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
879 /* Configuration make from file. */
880 int vtysh_config_from_file(struct vty
*vty
, FILE *fp
)
883 const struct cmd_element
*cmd
;
885 /* once we have an error, we remember & return that */
886 int retcode
= CMD_SUCCESS
;
888 while (fgets(vty
->buf
, VTY_BUFSIZ
, fp
)) {
891 ret
= command_config_read_one_line(vty
, &cmd
, lineno
, 1);
895 case CMD_WARNING_CONFIG_FAILED
:
896 if (vty
->type
== VTY_FILE
)
897 fprintf(stderr
, "line %d: Warning[%d]...: %s\n",
898 lineno
, vty
->node
, vty
->buf
);
902 case CMD_ERR_AMBIGUOUS
:
904 "line %d: %% Ambiguous command[%d]: %s\n",
905 lineno
, vty
->node
, vty
->buf
);
906 retcode
= CMD_ERR_AMBIGUOUS
;
908 case CMD_ERR_NO_MATCH
:
909 fprintf(stderr
, "line %d: %% Unknown command[%d]: %s",
910 lineno
, vty
->node
, vty
->buf
);
911 retcode
= CMD_ERR_NO_MATCH
;
913 case CMD_ERR_INCOMPLETE
:
915 "line %d: %% Command incomplete[%d]: %s\n",
916 lineno
, vty
->node
, vty
->buf
);
917 retcode
= CMD_ERR_INCOMPLETE
;
919 case CMD_SUCCESS_DAEMON
: {
921 int cmd_stat
= CMD_SUCCESS
;
923 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
924 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
925 cmd_stat
= vtysh_client_execute(
926 &vtysh_client
[i
], vty
->buf
);
928 * CMD_WARNING - Can mean that the
929 * command was parsed successfully but
930 * it was already entered in a few
931 * spots. As such if we receive a
932 * CMD_WARNING from a daemon we
933 * shouldn't stop talking to the other
934 * daemons for the particular command.
936 if (cmd_stat
!= CMD_SUCCESS
937 && cmd_stat
!= CMD_WARNING
) {
939 "line %d: Failure to communicate[%d] to %s, line: %s\n",
941 vtysh_client
[i
].name
,
948 if (cmd_stat
!= CMD_SUCCESS
)
952 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
961 * Function processes cli commands terminated with '?' character when entered
962 * through either 'vtysh' or 'vtysh -c' interfaces.
964 static int vtysh_process_questionmark(const char *input
, int input_len
)
968 vector vline
, describe
;
969 struct cmd_token
*token
;
974 vline
= cmd_make_strvec(input
);
976 /* In case of '> ?'. */
978 vline
= vector_init(1);
979 vector_set(vline
, NULL
);
980 } else if (input_len
&& isspace((unsigned char)input
[input_len
- 1]))
981 vector_set(vline
, NULL
);
983 describe
= cmd_describe_command(vline
, vty
, &ret
);
985 /* Ambiguous and no match error. */
987 case CMD_ERR_AMBIGUOUS
:
988 cmd_free_strvec(vline
);
989 vector_free(describe
);
990 vty_out(vty
, "%% Ambiguous command.\n");
993 case CMD_ERR_NO_MATCH
:
994 cmd_free_strvec(vline
);
996 vector_free(describe
);
997 vty_out(vty
, "%% There is no matched command.\n");
1002 /* Get width of command string. */
1004 for (i
= 0; i
< vector_active(describe
); i
++)
1005 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1006 if (token
->text
[0] == '\0')
1009 int len
= strlen(token
->text
);
1015 for (i
= 0; i
< vector_active(describe
); i
++)
1016 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1018 vty_out(vty
, " %-s\n", token
->text
);
1020 vty_out(vty
, " %-*s %s\n", width
, token
->text
,
1023 if (IS_VARYING_TOKEN(token
->type
)) {
1024 const char *ref
= vector_slot(
1025 vline
, vector_active(vline
) - 1);
1027 vector varcomps
= vector_init(VECTOR_MIN_SIZE
);
1028 cmd_variable_complete(token
, ref
, varcomps
);
1030 if (vector_active(varcomps
) > 0) {
1032 rl_get_screen_size(&rows
, &cols
);
1034 char *ac
= cmd_variable_comp2str(
1036 vty_out(vty
, "%s\n", ac
);
1037 XFREE(MTYPE_TMP
, ac
);
1040 vector_free(varcomps
);
1044 cmd_free_strvec(vline
);
1045 vector_free(describe
);
1051 * Entry point for user commands terminated with '?' character and typed through
1052 * the usual vtysh's stdin interface. This is the function being registered with
1055 static int vtysh_rl_describe(int a
, int b
)
1061 ret
= vtysh_process_questionmark(rl_line_buffer
, rl_end
);
1068 * Function in charged of processing vtysh instructions terminating with '?'
1069 * character and received through the 'vtysh -c' interface. If user's
1070 * instruction is well-formatted, we will call the same processing routine
1071 * utilized by the traditional vtysh's stdin interface.
1073 int vtysh_execute_command_questionmark(char *input
)
1075 int input_len
, qmark_count
= 0;
1078 if (!(input
&& *input
))
1081 /* Finding out question_mark count and strlen */
1082 for (str
= input
; *str
; ++str
) {
1086 input_len
= str
- input
;
1089 * Verify that user's input terminates in '?' and that patterns such as
1090 * 'cmd ? subcmd ?' are prevented.
1092 if (qmark_count
!= 1 || input
[input_len
- 1] != '?')
1096 * Questionmark-processing function is not expecting to receive '?'
1097 * character in input string.
1099 input
[input_len
- 1] = '\0';
1101 return vtysh_process_questionmark(input
, input_len
- 1);
1104 /* Result of cmd_complete_command() call will be stored here
1105 * and used in new_completion() in order to put the space in
1106 * correct places only. */
1107 int complete_status
;
1109 static char *command_generator(const char *text
, int state
)
1112 static char **matched
= NULL
;
1113 static int index
= 0;
1119 if (vty
->node
== AUTH_NODE
|| vty
->node
== AUTH_ENABLE_NODE
)
1122 vline
= cmd_make_strvec(rl_line_buffer
);
1127 isspace((unsigned char)rl_line_buffer
[rl_end
- 1]))
1128 vector_set(vline
, NULL
);
1130 matched
= cmd_complete_command(vline
, vty
, &complete_status
);
1131 cmd_free_strvec(vline
);
1134 if (matched
&& matched
[index
]) {
1135 XCOUNTFREE(MTYPE_COMPLETION
, matched
[index
]);
1136 return matched
[index
++];
1139 XFREE(MTYPE_TMP
, matched
);
1144 static char **new_completion(const char *text
, int start
, int end
)
1148 matches
= rl_completion_matches(text
, command_generator
);
1152 if (complete_status
!= CMD_COMPLETE_FULL_MATCH
)
1153 /* only append a space on full match */
1154 rl_completion_append_character
= '\0';
1160 /* Vty node structures. */
1162 static struct cmd_node bgp_node
= {
1165 .parent_node
= CONFIG_NODE
,
1166 .prompt
= "%s(config-router)# ",
1168 #endif /* HAVE_BGPD */
1170 static struct cmd_node rip_node
= {
1173 .parent_node
= CONFIG_NODE
,
1174 .prompt
= "%s(config-router)# ",
1178 static struct cmd_node isis_node
= {
1181 .parent_node
= CONFIG_NODE
,
1182 .prompt
= "%s(config-router)# ",
1184 #endif /* HAVE_ISISD */
1187 static struct cmd_node openfabric_node
= {
1188 .name
= "openfabric",
1189 .node
= OPENFABRIC_NODE
,
1190 .parent_node
= CONFIG_NODE
,
1191 .prompt
= "%s(config-router)# ",
1193 #endif /* HAVE_FABRICD */
1195 static struct cmd_node interface_node
= {
1196 .name
= "interface",
1197 .node
= INTERFACE_NODE
,
1198 .parent_node
= CONFIG_NODE
,
1199 .prompt
= "%s(config-if)# ",
1202 static struct cmd_node pw_node
= {
1205 .parent_node
= CONFIG_NODE
,
1206 .prompt
= "%s(config-pw)# ",
1209 static struct cmd_node segment_routing_node
= {
1210 .name
= "segment-routing",
1211 .node
= SEGMENT_ROUTING_NODE
,
1212 .parent_node
= CONFIG_NODE
,
1213 .prompt
= "%s(config-sr)# ",
1216 #if defined(HAVE_PATHD)
1217 static struct cmd_node sr_traffic_eng_node
= {
1218 .name
= "sr traffic-eng",
1219 .node
= SR_TRAFFIC_ENG_NODE
,
1220 .parent_node
= SEGMENT_ROUTING_NODE
,
1221 .prompt
= "%s(config-sr-te)# ",
1224 static struct cmd_node srte_segment_list_node
= {
1225 .name
= "srte segment-list",
1226 .node
= SR_SEGMENT_LIST_NODE
,
1227 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1228 .prompt
= "%s(config-sr-te-segment-list)# ",
1231 static struct cmd_node srte_policy_node
= {
1232 .name
= "srte policy",
1233 .node
= SR_POLICY_NODE
,
1234 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1235 .prompt
= "%s(config-sr-te-policy)# ",
1238 static struct cmd_node srte_candidate_dyn_node
= {
1239 .name
= "srte candidate-dyn",
1240 .node
= SR_CANDIDATE_DYN_NODE
,
1241 .parent_node
= SR_POLICY_NODE
,
1242 .prompt
= "%s(config-sr-te-candidate)# ",
1245 static struct cmd_node pcep_node
= {
1246 .name
= "srte pcep",
1248 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1249 .prompt
= "%s(config-sr-te-pcep)# "
1252 static struct cmd_node pcep_pcc_node
= {
1253 .name
= "srte pcep pcc",
1254 .node
= PCEP_PCC_NODE
,
1255 .parent_node
= PCEP_NODE
,
1256 .prompt
= "%s(config-sr-te-pcep-pcc)# ",
1259 static struct cmd_node pcep_pce_node
= {
1260 .name
= "srte pcep pce-peer",
1261 .node
= PCEP_PCE_NODE
,
1262 .parent_node
= PCEP_NODE
,
1263 .prompt
= "%s(config-sr-te-pcep-pce-peer)# ",
1266 static struct cmd_node pcep_pce_config_node
= {
1267 .name
= "srte pcep pce-config",
1268 .node
= PCEP_PCE_CONFIG_NODE
,
1269 .parent_node
= PCEP_NODE
,
1270 .prompt
= "%s(pcep-sr-te-pcep-pce-config)# ",
1272 #endif /* HAVE_PATHD */
1274 static struct cmd_node vrf_node
= {
1277 .parent_node
= CONFIG_NODE
,
1278 .prompt
= "%s(config-vrf)# ",
1281 static struct cmd_node nh_group_node
= {
1282 .name
= "nexthop-group",
1283 .node
= NH_GROUP_NODE
,
1284 .parent_node
= CONFIG_NODE
,
1285 .prompt
= "%s(config-nh-group)# ",
1288 static struct cmd_node rmap_node
= {
1291 .parent_node
= CONFIG_NODE
,
1292 .prompt
= "%s(config-route-map)# ",
1295 static struct cmd_node srv6_node
= {
1298 .parent_node
= SEGMENT_ROUTING_NODE
,
1299 .prompt
= "%s(config-srv6)# ",
1302 static struct cmd_node srv6_locs_node
= {
1303 .name
= "srv6-locators",
1304 .node
= SRV6_LOCS_NODE
,
1305 .parent_node
= SRV6_NODE
,
1306 .prompt
= "%s(config-srv6-locators)# ",
1309 static struct cmd_node srv6_loc_node
= {
1310 .name
= "srv6-locator",
1311 .node
= SRV6_LOC_NODE
,
1312 .parent_node
= SRV6_LOCS_NODE
,
1313 .prompt
= "%s(config-srv6-locator)# ",
1317 static struct cmd_node pbr_map_node
= {
1319 .node
= PBRMAP_NODE
,
1320 .parent_node
= CONFIG_NODE
,
1321 .prompt
= "%s(config-pbr-map)# ",
1323 #endif /* HAVE_PBRD */
1325 static struct cmd_node zebra_node
= {
1328 .parent_node
= CONFIG_NODE
,
1329 .prompt
= "%s(config-router)# ",
1333 static struct cmd_node bgp_vpnv4_node
= {
1334 .name
= "bgp vpnv4",
1335 .node
= BGP_VPNV4_NODE
,
1336 .parent_node
= BGP_NODE
,
1337 .prompt
= "%s(config-router-af)# ",
1341 static struct cmd_node bgp_vpnv6_node
= {
1342 .name
= "bgp vpnv6",
1343 .node
= BGP_VPNV6_NODE
,
1344 .parent_node
= BGP_NODE
,
1345 .prompt
= "%s(config-router-af)# ",
1349 static struct cmd_node bgp_flowspecv4_node
= {
1350 .name
= "bgp ipv4 flowspec",
1351 .node
= BGP_FLOWSPECV4_NODE
,
1352 .parent_node
= BGP_NODE
,
1353 .prompt
= "%s(config-router-af)# ",
1357 static struct cmd_node bgp_flowspecv6_node
= {
1358 .name
= "bgp ipv6 flowspec",
1359 .node
= BGP_FLOWSPECV6_NODE
,
1360 .parent_node
= BGP_NODE
,
1361 .prompt
= "%s(config-router-af)# ",
1365 static struct cmd_node bgp_ipv4_node
= {
1366 .name
= "bgp ipv4 unicast",
1367 .node
= BGP_IPV4_NODE
,
1368 .parent_node
= BGP_NODE
,
1369 .prompt
= "%s(config-router-af)# ",
1373 static struct cmd_node bgp_ipv4m_node
= {
1374 .name
= "bgp ipv4 multicast",
1375 .node
= BGP_IPV4M_NODE
,
1376 .parent_node
= BGP_NODE
,
1377 .prompt
= "%s(config-router-af)# ",
1381 static struct cmd_node bgp_ipv4l_node
= {
1382 .name
= "bgp ipv4 labeled unicast",
1383 .node
= BGP_IPV4L_NODE
,
1384 .parent_node
= BGP_NODE
,
1385 .prompt
= "%s(config-router-af)# ",
1389 static struct cmd_node bgp_ipv6_node
= {
1391 .node
= BGP_IPV6_NODE
,
1392 .parent_node
= BGP_NODE
,
1393 .prompt
= "%s(config-router-af)# ",
1397 static struct cmd_node bgp_ipv6m_node
= {
1398 .name
= "bgp ipv6 multicast",
1399 .node
= BGP_IPV6M_NODE
,
1400 .parent_node
= BGP_NODE
,
1401 .prompt
= "%s(config-router-af)# ",
1405 static struct cmd_node bgp_evpn_node
= {
1407 .node
= BGP_EVPN_NODE
,
1408 .parent_node
= BGP_NODE
,
1409 .prompt
= "%s(config-router-af)# ",
1413 static struct cmd_node bgp_evpn_vni_node
= {
1414 .name
= "bgp evpn vni",
1415 .node
= BGP_EVPN_VNI_NODE
,
1416 .parent_node
= BGP_EVPN_NODE
,
1417 .prompt
= "%s(config-router-af-vni)# ",
1420 static struct cmd_node bgp_ipv6l_node
= {
1421 .name
= "bgp ipv6 labeled unicast",
1422 .node
= BGP_IPV6L_NODE
,
1423 .parent_node
= BGP_NODE
,
1424 .prompt
= "%s(config-router-af)# ",
1428 #ifdef ENABLE_BGP_VNC
1429 static struct cmd_node bgp_vnc_defaults_node
= {
1430 .name
= "bgp vnc defaults",
1431 .node
= BGP_VNC_DEFAULTS_NODE
,
1432 .parent_node
= BGP_NODE
,
1433 .prompt
= "%s(config-router-vnc-defaults)# ",
1436 static struct cmd_node bgp_vnc_nve_group_node
= {
1437 .name
= "bgp vnc nve",
1438 .node
= BGP_VNC_NVE_GROUP_NODE
,
1439 .parent_node
= BGP_NODE
,
1440 .prompt
= "%s(config-router-vnc-nve-group)# ",
1443 static struct cmd_node bgp_vrf_policy_node
= {
1444 .name
= "bgp vrf policy",
1445 .node
= BGP_VRF_POLICY_NODE
,
1446 .parent_node
= BGP_NODE
,
1447 .prompt
= "%s(config-router-vrf-policy)# ",
1450 static struct cmd_node bgp_vnc_l2_group_node
= {
1451 .name
= "bgp vnc l2",
1452 .node
= BGP_VNC_L2_GROUP_NODE
,
1453 .parent_node
= BGP_NODE
,
1454 .prompt
= "%s(config-router-vnc-l2-group)# ",
1456 #endif /* ENABLE_BGP_VNC */
1458 static struct cmd_node bmp_node
= {
1461 .parent_node
= BGP_NODE
,
1462 .prompt
= "%s(config-bgp-bmp)# "
1465 static struct cmd_node bgp_srv6_node
= {
1467 .node
= BGP_SRV6_NODE
,
1468 .parent_node
= BGP_NODE
,
1469 .prompt
= "%s(config-router-srv6)# ",
1471 #endif /* HAVE_BGPD */
1474 static struct cmd_node ospf_node
= {
1477 .parent_node
= CONFIG_NODE
,
1478 .prompt
= "%s(config-router)# ",
1480 #endif /* HAVE_OSPFD */
1483 static struct cmd_node eigrp_node
= {
1486 .parent_node
= CONFIG_NODE
,
1487 .prompt
= "%s(config-router)# ",
1489 #endif /* HAVE_EIGRPD */
1492 static struct cmd_node babel_node
= {
1495 .parent_node
= CONFIG_NODE
,
1496 .prompt
= "%s(config-router)# ",
1498 #endif /* HAVE_BABELD */
1500 static struct cmd_node ripng_node
= {
1503 .parent_node
= CONFIG_NODE
,
1504 .prompt
= "%s(config-router)# ",
1508 static struct cmd_node ospf6_node
= {
1511 .parent_node
= CONFIG_NODE
,
1512 .prompt
= "%s(config-ospf6)# ",
1514 #endif /* HAVE_OSPF6D */
1517 static struct cmd_node ldp_node
= {
1520 .parent_node
= CONFIG_NODE
,
1521 .prompt
= "%s(config-ldp)# ",
1524 static struct cmd_node ldp_ipv4_node
= {
1526 .node
= LDP_IPV4_NODE
,
1527 .parent_node
= LDP_NODE
,
1528 .prompt
= "%s(config-ldp-af)# ",
1531 static struct cmd_node ldp_ipv6_node
= {
1533 .node
= LDP_IPV6_NODE
,
1534 .parent_node
= LDP_NODE
,
1535 .prompt
= "%s(config-ldp-af)# ",
1538 static struct cmd_node ldp_ipv4_iface_node
= {
1539 .name
= "ldp ipv4 interface",
1540 .node
= LDP_IPV4_IFACE_NODE
,
1541 .parent_node
= LDP_IPV4_NODE
,
1542 .prompt
= "%s(config-ldp-af-if)# ",
1545 static struct cmd_node ldp_ipv6_iface_node
= {
1546 .name
= "ldp ipv6 interface",
1547 .node
= LDP_IPV6_IFACE_NODE
,
1548 .parent_node
= LDP_IPV6_NODE
,
1549 .prompt
= "%s(config-ldp-af-if)# ",
1552 static struct cmd_node ldp_l2vpn_node
= {
1553 .name
= "ldp l2vpn",
1554 .node
= LDP_L2VPN_NODE
,
1555 .parent_node
= CONFIG_NODE
,
1556 .prompt
= "%s(config-l2vpn)# ",
1559 static struct cmd_node ldp_pseudowire_node
= {
1561 .node
= LDP_PSEUDOWIRE_NODE
,
1562 .parent_node
= LDP_L2VPN_NODE
,
1563 .prompt
= "%s(config-l2vpn-pw)# ",
1565 #endif /* HAVE_LDPD */
1567 static struct cmd_node keychain_node
= {
1569 .node
= KEYCHAIN_NODE
,
1570 .parent_node
= CONFIG_NODE
,
1571 .prompt
= "%s(config-keychain)# ",
1574 static struct cmd_node keychain_key_node
= {
1575 .name
= "keychain key",
1576 .node
= KEYCHAIN_KEY_NODE
,
1577 .parent_node
= KEYCHAIN_NODE
,
1578 .prompt
= "%s(config-keychain-key)# ",
1581 struct cmd_node link_params_node
= {
1582 .name
= "link-params",
1583 .node
= LINK_PARAMS_NODE
,
1584 .parent_node
= INTERFACE_NODE
,
1585 .prompt
= "%s(config-link-params)# ",
1590 static struct cmd_node rpki_node
= {
1593 .parent_node
= CONFIG_NODE
,
1594 .prompt
= "%s(config-rpki)# ",
1596 #endif /* HAVE_BGPD */
1599 static struct cmd_node bfd_node
= {
1602 .parent_node
= CONFIG_NODE
,
1603 .prompt
= "%s(config-bfd)# ",
1606 static struct cmd_node bfd_peer_node
= {
1608 .node
= BFD_PEER_NODE
,
1609 .parent_node
= BFD_NODE
,
1610 .prompt
= "%s(config-bfd-peer)# ",
1613 static struct cmd_node bfd_profile_node
= {
1614 .name
= "bfd profile",
1615 .node
= BFD_PROFILE_NODE
,
1616 .parent_node
= BFD_NODE
,
1617 .prompt
= "%s(config-bfd-profile)# ",
1619 #endif /* HAVE_BFDD */
1621 /* Defined in lib/vty.c */
1622 extern struct cmd_node vty_node
;
1624 /* When '^Z' is received from vty, move down to the enable mode. */
1625 static int vtysh_end(void)
1627 switch (vty
->node
) {
1630 /* Nothing to do. */
1633 vty
->node
= ENABLE_NODE
;
1639 #include "vtysh/vtysh_clippy.c"
1641 DEFUNSH(VTYSH_REALLYALL
, vtysh_end_all
, vtysh_end_all_cmd
, "end",
1642 "End current mode and change to enable mode\n")
1647 DEFUNSH(VTYSH_ZEBRA
, srv6
, srv6_cmd
,
1649 "Segment-Routing SRv6 configuration\n")
1651 vty
->node
= SRV6_NODE
;
1655 DEFUNSH(VTYSH_ZEBRA
, srv6_locators
, srv6_locators_cmd
,
1657 "Segment-Routing SRv6 locators configuration\n")
1659 vty
->node
= SRV6_LOCS_NODE
;
1663 DEFUNSH(VTYSH_ZEBRA
, srv6_locator
, srv6_locator_cmd
,
1665 "Segment Routing SRv6 locator\n"
1666 "Specify locator-name\n")
1668 vty
->node
= SRV6_LOC_NODE
;
1673 DEFUNSH(VTYSH_BGPD
, router_bgp
, router_bgp_cmd
,
1674 "router bgp [(1-4294967295) [<view|vrf> WORD]]",
1675 ROUTER_STR BGP_STR AS_STR
1676 "BGP view\nBGP VRF\n"
1679 vty
->node
= BGP_NODE
;
1683 #ifdef KEEP_OLD_VPN_COMMANDS
1684 DEFUNSH(VTYSH_BGPD
, address_family_vpnv4
, address_family_vpnv4_cmd
,
1685 "address-family vpnv4 [unicast]",
1686 "Enter Address Family command mode\n"
1688 "Address Family modifier\n")
1690 vty
->node
= BGP_VPNV4_NODE
;
1694 DEFUNSH(VTYSH_BGPD
, address_family_vpnv6
, address_family_vpnv6_cmd
,
1695 "address-family vpnv6 [unicast]",
1696 "Enter Address Family command mode\n"
1698 "Address Family modifier\n")
1700 vty
->node
= BGP_VPNV6_NODE
;
1703 #endif /* KEEP_OLD_VPN_COMMANDS */
1705 DEFUNSH(VTYSH_BGPD
, address_family_ipv4
, address_family_ipv4_cmd
,
1706 "address-family ipv4 [unicast]",
1707 "Enter Address Family command mode\n"
1709 "Address Family Modifier\n")
1711 vty
->node
= BGP_IPV4_NODE
;
1715 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv4
, address_family_flowspecv4_cmd
,
1716 "address-family ipv4 flowspec",
1717 "Enter Address Family command mode\n"
1719 "Address Family Modifier\n")
1721 vty
->node
= BGP_FLOWSPECV4_NODE
;
1725 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv6
, address_family_flowspecv6_cmd
,
1726 "address-family ipv6 flowspec",
1727 "Enter Address Family command mode\n"
1729 "Address Family Modifier\n")
1731 vty
->node
= BGP_FLOWSPECV6_NODE
;
1735 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_multicast
,
1736 address_family_ipv4_multicast_cmd
, "address-family ipv4 multicast",
1737 "Enter Address Family command mode\n"
1739 "Address Family modifier\n")
1741 vty
->node
= BGP_IPV4M_NODE
;
1745 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_vpn
, address_family_ipv4_vpn_cmd
,
1746 "address-family ipv4 vpn",
1747 "Enter Address Family command mode\n"
1749 "Address Family modifier\n")
1751 vty
->node
= BGP_VPNV4_NODE
;
1755 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_labeled_unicast
,
1756 address_family_ipv4_labeled_unicast_cmd
,
1757 "address-family ipv4 labeled-unicast",
1758 "Enter Address Family command mode\n"
1760 "Address Family modifier\n")
1762 vty
->node
= BGP_IPV4L_NODE
;
1766 DEFUNSH(VTYSH_BGPD
, address_family_ipv6
, address_family_ipv6_cmd
,
1767 "address-family ipv6 [unicast]",
1768 "Enter Address Family command mode\n"
1770 "Address Family modifier\n")
1772 vty
->node
= BGP_IPV6_NODE
;
1776 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_multicast
,
1777 address_family_ipv6_multicast_cmd
, "address-family ipv6 multicast",
1778 "Enter Address Family command mode\n"
1780 "Address Family modifier\n")
1782 vty
->node
= BGP_IPV6M_NODE
;
1786 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_vpn
, address_family_ipv6_vpn_cmd
,
1787 "address-family ipv6 vpn",
1788 "Enter Address Family command mode\n"
1790 "Address Family modifier\n")
1792 vty
->node
= BGP_VPNV6_NODE
;
1796 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_labeled_unicast
,
1797 address_family_ipv6_labeled_unicast_cmd
,
1798 "address-family ipv6 labeled-unicast",
1799 "Enter Address Family command mode\n"
1801 "Address Family modifier\n")
1803 vty
->node
= BGP_IPV6L_NODE
;
1811 "Enable rpki and enter rpki configuration mode\n")
1813 vty
->node
= RPKI_NODE
;
1820 "bmp targets BMPTARGETS",
1821 "BGP Monitoring Protocol\n"
1822 "Create BMP target group\n"
1823 "Name of the BMP target group\n")
1825 vty
->node
= BMP_NODE
;
1832 "segment-routing srv6",
1833 "Segment-Routing configuration\n"
1834 "Segment-Routing SRv6 configuration\n")
1836 vty
->node
= BGP_SRV6_NODE
;
1844 "exit Segment-Routing SRv6 configuration\n")
1846 if (vty
->node
== BGP_SRV6_NODE
)
1847 vty
->node
= BGP_NODE
;
1855 "quit Segment-Routing SRv6 configuration\n")
1857 if (vty
->node
== BGP_SRV6_NODE
)
1858 vty
->node
= BGP_NODE
;
1862 DEFUNSH(VTYSH_BGPD
, address_family_evpn
, address_family_evpn_cmd
,
1863 "address-family <l2vpn evpn>",
1864 "Enter Address Family command mode\n"
1866 "Address Family modifier\n")
1868 vty
->node
= BGP_EVPN_NODE
;
1872 DEFUNSH(VTYSH_BGPD
, bgp_evpn_vni
, bgp_evpn_vni_cmd
, "vni " CMD_VNI_RANGE
,
1873 "VXLAN Network Identifier\n"
1876 vty
->node
= BGP_EVPN_VNI_NODE
;
1880 #if defined(ENABLE_BGP_VNC)
1881 DEFUNSH(VTYSH_BGPD
, vnc_defaults
, vnc_defaults_cmd
, "vnc defaults",
1882 "VNC/RFP related configuration\n"
1883 "Configure default NVE group\n")
1885 vty
->node
= BGP_VNC_DEFAULTS_NODE
;
1889 DEFUNSH(VTYSH_BGPD
, vnc_nve_group
, vnc_nve_group_cmd
, "vnc nve-group NAME",
1890 "VNC/RFP related configuration\n"
1891 "Configure a NVE group\n"
1894 vty
->node
= BGP_VNC_NVE_GROUP_NODE
;
1898 DEFUNSH(VTYSH_BGPD
, vnc_vrf_policy
, vnc_vrf_policy_cmd
, "vrf-policy NAME",
1899 "Configure a VRF policy group\n"
1902 vty
->node
= BGP_VRF_POLICY_NODE
;
1906 DEFUNSH(VTYSH_BGPD
, vnc_l2_group
, vnc_l2_group_cmd
, "vnc l2-group NAME",
1907 "VNC/RFP related configuration\n"
1908 "Configure a L2 group\n"
1911 vty
->node
= BGP_VNC_L2_GROUP_NODE
;
1915 DEFUNSH(VTYSH_BGPD
, exit_vnc_config
, exit_vnc_config_cmd
, "exit-vnc",
1916 "Exit from VNC configuration mode\n")
1918 if (vty
->node
== BGP_VNC_DEFAULTS_NODE
1919 || vty
->node
== BGP_VNC_NVE_GROUP_NODE
1920 || vty
->node
== BGP_VNC_L2_GROUP_NODE
)
1921 vty
->node
= BGP_NODE
;
1925 DEFUNSH(VTYSH_BGPD
, exit_vrf_policy
, exit_vrf_policy_cmd
, "exit-vrf-policy",
1926 "Exit from VRF policy configuration mode\n")
1928 if (vty
->node
== BGP_VRF_POLICY_NODE
)
1929 vty
->node
= BGP_NODE
;
1933 #endif /* HAVE_BGPD */
1935 DEFUNSH(VTYSH_KEYS
, key_chain
, key_chain_cmd
, "key chain WORD",
1936 "Authentication key management\n"
1937 "Key-chain management\n"
1940 vty
->node
= KEYCHAIN_NODE
;
1944 DEFUNSH(VTYSH_KEYS
, key
, key_cmd
, "key (0-2147483647)",
1946 "Key identifier number\n")
1948 vty
->node
= KEYCHAIN_KEY_NODE
;
1953 DEFUNSH(VTYSH_RIPD
, router_rip
, router_rip_cmd
, "router rip [vrf NAME]",
1954 ROUTER_STR
"RIP\n" VRF_CMD_HELP_STR
)
1956 vty
->node
= RIP_NODE
;
1959 #endif /* HAVE_RIPD */
1962 DEFUNSH(VTYSH_RIPNGD
, router_ripng
, router_ripng_cmd
, "router ripng [vrf NAME]",
1963 ROUTER_STR
"RIPng\n" VRF_CMD_HELP_STR
)
1965 vty
->node
= RIPNG_NODE
;
1968 #endif /* HAVE_RIPNGD */
1971 DEFUNSH(VTYSH_OSPFD
, router_ospf
, router_ospf_cmd
,
1972 "router ospf [(1-65535)] [vrf NAME]",
1973 "Enable a routing process\n"
1974 "Start OSPF configuration\n"
1978 vty
->node
= OSPF_NODE
;
1981 #endif /* HAVE_OSPFD */
1984 DEFUNSH(VTYSH_EIGRPD
, router_eigrp
, router_eigrp_cmd
, "router eigrp (1-65535) [vrf NAME]",
1985 "Enable a routing process\n"
1986 "Start EIGRP configuration\n"
1987 "AS number to use\n"
1990 vty
->node
= EIGRP_NODE
;
1993 #endif /* HAVE_EIGRPD */
1996 DEFUNSH(VTYSH_BABELD
, router_babel
, router_babel_cmd
, "router babel",
1997 "Enable a routing process\n"
1998 "Make Babel instance command\n")
2000 vty
->node
= BABEL_NODE
;
2003 #endif /* HAVE_BABELD */
2006 DEFUNSH(VTYSH_OSPF6D
, router_ospf6
, router_ospf6_cmd
, "router ospf6 [vrf NAME]",
2007 ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR
)
2009 vty
->node
= OSPF6_NODE
;
2014 #if defined(HAVE_LDPD)
2015 DEFUNSH(VTYSH_LDPD
, ldp_mpls_ldp
, ldp_mpls_ldp_cmd
, "mpls ldp",
2016 "Global MPLS configuration subcommands\n"
2017 "Label Distribution Protocol\n")
2019 vty
->node
= LDP_NODE
;
2023 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv4
, ldp_address_family_ipv4_cmd
,
2024 "address-family ipv4",
2025 "Configure Address Family and its parameters\n"
2028 vty
->node
= LDP_IPV4_NODE
;
2032 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv6
, ldp_address_family_ipv6_cmd
,
2033 "address-family ipv6",
2034 "Configure Address Family and its parameters\n"
2037 vty
->node
= LDP_IPV6_NODE
;
2041 DEFUNSH(VTYSH_LDPD
, ldp_exit_address_family
, ldp_exit_address_family_cmd
,
2042 "exit-address-family", "Exit from Address Family configuration mode\n")
2044 if (vty
->node
== LDP_IPV4_NODE
|| vty
->node
== LDP_IPV6_NODE
)
2045 vty
->node
= LDP_NODE
;
2049 DEFUNSH(VTYSH_LDPD
, ldp_interface_ifname
, ldp_interface_ifname_cmd
,
2051 "Enable LDP on an interface and enter interface submode\n"
2052 "Interface's name\n")
2054 switch (vty
->node
) {
2056 vty
->node
= LDP_IPV4_IFACE_NODE
;
2059 vty
->node
= LDP_IPV6_IFACE_NODE
;
2068 DEFUNSH(VTYSH_LDPD
, ldp_l2vpn_word_type_vpls
, ldp_l2vpn_word_type_vpls_cmd
,
2069 "l2vpn WORD type vpls",
2070 "Configure l2vpn commands\n"
2073 "Virtual Private LAN Service\n")
2075 vty
->node
= LDP_L2VPN_NODE
;
2079 DEFUNSH(VTYSH_LDPD
, ldp_member_pseudowire_ifname
,
2080 ldp_member_pseudowire_ifname_cmd
, "member pseudowire IFNAME",
2081 "L2VPN member configuration\n"
2082 "Pseudowire interface\n"
2083 "Interface's name\n")
2085 vty
->node
= LDP_PSEUDOWIRE_NODE
;
2091 DEFUNSH(VTYSH_ISISD
, router_isis
, router_isis_cmd
,
2092 "router isis WORD [vrf NAME]",
2095 "ISO Routing area tag\n" VRF_CMD_HELP_STR
)
2097 vty
->node
= ISIS_NODE
;
2100 #endif /* HAVE_ISISD */
2103 DEFUNSH(VTYSH_FABRICD
, router_openfabric
, router_openfabric_cmd
, "router openfabric WORD",
2105 "OpenFabric routing protocol\n"
2106 "ISO Routing area tag\n")
2108 vty
->node
= OPENFABRIC_NODE
;
2111 #endif /* HAVE_FABRICD */
2113 DEFUNSH(VTYSH_SR
, segment_routing
, segment_routing_cmd
,
2115 "Configure segment routing\n")
2117 vty
->node
= SEGMENT_ROUTING_NODE
;
2121 #if defined (HAVE_PATHD)
2122 DEFUNSH(VTYSH_PATHD
, sr_traffic_eng
, sr_traffic_eng_cmd
,
2124 "Configure SR traffic engineering\n")
2126 vty
->node
= SR_TRAFFIC_ENG_NODE
;
2130 DEFUNSH(VTYSH_PATHD
, srte_segment_list
, srte_segment_list_cmd
,
2131 "segment-list WORD$name",
2133 "Segment List Name\n")
2135 vty
->node
= SR_SEGMENT_LIST_NODE
;
2139 DEFUNSH(VTYSH_PATHD
, srte_policy
, srte_policy_cmd
,
2140 "policy color (0-4294967295) endpoint <A.B.C.D|X:X::X:X>",
2141 "Segment Routing Policy\n"
2143 "SR Policy color value\n"
2144 "SR Policy endpoint\n"
2145 "SR Policy endpoint IPv4 address\n"
2146 "SR Policy endpoint IPv6 address\n")
2148 vty
->node
= SR_POLICY_NODE
;
2152 DEFUNSH(VTYSH_PATHD
, srte_policy_candidate_dyn_path
,
2153 srte_policy_candidate_dyn_path_cmd
,
2154 "candidate-path preference (0-4294967295) name WORD dynamic",
2155 "Segment Routing Policy Candidate Path\n"
2156 "Segment Routing Policy Candidate Path Preference\n"
2157 "Administrative Preference\n"
2158 "Segment Routing Policy Candidate Path Name\n"
2162 vty
->node
= SR_CANDIDATE_DYN_NODE
;
2166 DEFUNSH(VTYSH_PATHD
, pcep
, pcep_cmd
,
2168 "Configure SR pcep\n")
2170 vty
->node
= PCEP_NODE
;
2174 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcc
, pcep_cli_pcc_cmd
,
2176 "PCC configuration\n")
2178 vty
->node
= PCEP_PCC_NODE
;
2182 DEFUNSH(VTYSH_PATHD
, pcep_cli_pce
, pcep_cli_pce_cmd
,
2184 "PCE configuration\n"
2187 vty
->node
= PCEP_PCE_NODE
;
2191 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcep_pce_config
, pcep_cli_pcep_pce_config_cmd
,
2193 "PCEP peer Configuration Group\n"
2194 "PCEP peer Configuration Group name\n")
2196 vty
->node
= PCEP_PCE_CONFIG_NODE
;
2200 #endif /* HAVE_PATHD */
2202 DEFUNSH(VTYSH_RMAP
, vtysh_route_map
, vtysh_route_map_cmd
,
2203 "route-map RMAP_NAME <deny|permit> (1-65535)",
2204 "Create route-map or enter route-map command mode\n"
2206 "Route map denies set operations\n"
2207 "Route map permits set operations\n"
2208 "Sequence to insert to/delete from existing route-map entry\n")
2210 vty
->node
= RMAP_NODE
;
2215 DEFUNSH(VTYSH_PBRD
, vtysh_pbr_map
, vtysh_pbr_map_cmd
,
2216 "pbr-map PBRMAP seq (1-700)",
2217 "Create pbr-map or enter pbr-map command mode\n"
2218 "The name of the PBR MAP\n"
2219 "Sequence to insert to/delete from existing pbr-map entry\n"
2220 "Sequence number\n")
2222 vty
->node
= PBRMAP_NODE
;
2226 DEFSH(VTYSH_PBRD
, vtysh_no_pbr_map_cmd
, "no pbr-map PBRMAP [seq (1-700)]",
2229 "The name of the PBR MAP\n"
2230 "Sequence to delete from existing pbr-map entry\n"
2231 "Sequence number\n")
2232 #endif /* HAVE_PBRD */
2235 DEFUNSH(VTYSH_BFDD
, bfd_enter
, bfd_enter_cmd
, "bfd", "Configure BFD peers\n")
2237 vty
->node
= BFD_NODE
;
2241 DEFUNSH(VTYSH_BFDD
, bfd_peer_enter
, bfd_peer_enter_cmd
,
2242 "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
2244 "IPv4 peer address\n"
2245 "IPv6 peer address\n"
2246 "Configure multihop\n"
2247 "Configure local address\n"
2248 "IPv4 local address\n"
2249 "IPv6 local address\n"
2251 "Configure interface name to use\n"
2253 "Configure VRF name\n")
2255 vty
->node
= BFD_PEER_NODE
;
2259 DEFUNSH(VTYSH_BFDD
, bfd_profile_enter
, bfd_profile_enter_cmd
,
2262 BFD_PROFILE_NAME_STR
)
2264 vty
->node
= BFD_PROFILE_NODE
;
2267 #endif /* HAVE_BFDD */
2269 DEFUNSH(VTYSH_ALL
, vtysh_line_vty
, vtysh_line_vty_cmd
, "line vty",
2270 "Configure a terminal line\n"
2271 "Virtual terminal\n")
2273 vty
->node
= VTY_NODE
;
2277 DEFUNSH(VTYSH_REALLYALL
, vtysh_enable
, vtysh_enable_cmd
, "enable",
2278 "Turn on privileged mode command\n")
2280 vty
->node
= ENABLE_NODE
;
2284 DEFUNSH(VTYSH_REALLYALL
, vtysh_disable
, vtysh_disable_cmd
, "disable",
2285 "Turn off privileged mode command\n")
2287 if (vty
->node
== ENABLE_NODE
)
2288 vty
->node
= VIEW_NODE
;
2292 DEFUNSH(VTYSH_REALLYALL
, vtysh_config_terminal
, vtysh_config_terminal_cmd
,
2293 "configure [terminal]",
2294 "Configuration from vty interface\n"
2295 "Configuration terminal\n")
2297 vty
->node
= CONFIG_NODE
;
2301 static int vtysh_exit(struct vty
*vty
)
2303 struct cmd_node
*cnode
= vector_lookup(cmdvec
, vty
->node
);
2305 if (vty
->node
== VIEW_NODE
|| vty
->node
== ENABLE_NODE
)
2307 if (cnode
->node_exit
)
2308 cnode
->node_exit(vty
);
2309 if (cnode
->parent_node
)
2310 vty
->node
= cnode
->parent_node
;
2312 if (vty
->node
== CONFIG_NODE
) {
2313 /* resync in case one of the daemons is somewhere else */
2314 vtysh_execute("end");
2315 vtysh_execute("configure");
2320 DEFUNSH(VTYSH_REALLYALL
, vtysh_exit_all
, vtysh_exit_all_cmd
, "exit",
2321 "Exit current mode and down to previous mode\n")
2323 return vtysh_exit(vty
);
2326 DEFUNSH(VTYSH_REALLYALL
, vtysh_quit_all
, vtysh_quit_all_cmd
, "quit",
2327 "Exit current mode and down to previous mode\n")
2329 return vtysh_exit_all(self
, vty
, argc
, argv
);
2333 DEFUNSH(VTYSH_BGPD
, exit_address_family
, exit_address_family_cmd
,
2334 "exit-address-family", "Exit from Address Family configuration mode\n")
2336 if (vty
->node
== BGP_IPV4_NODE
|| vty
->node
== BGP_IPV4M_NODE
2337 || vty
->node
== BGP_IPV4L_NODE
|| vty
->node
== BGP_VPNV4_NODE
2338 || vty
->node
== BGP_VPNV6_NODE
|| vty
->node
== BGP_IPV6_NODE
2339 || vty
->node
== BGP_IPV6L_NODE
|| vty
->node
== BGP_IPV6M_NODE
2340 || vty
->node
== BGP_EVPN_NODE
2341 || vty
->node
== BGP_FLOWSPECV4_NODE
2342 || vty
->node
== BGP_FLOWSPECV6_NODE
)
2343 vty
->node
= BGP_NODE
;
2347 DEFUNSH(VTYSH_BGPD
, exit_vni
, exit_vni_cmd
, "exit-vni", "Exit from VNI mode\n")
2349 if (vty
->node
== BGP_EVPN_VNI_NODE
)
2350 vty
->node
= BGP_EVPN_NODE
;
2354 DEFUNSH(VTYSH_BGPD
, rpki_exit
, rpki_exit_cmd
, "exit",
2355 "Exit current mode and down to previous mode\n")
2361 DEFUNSH(VTYSH_BGPD
, rpki_quit
, rpki_quit_cmd
, "quit",
2362 "Exit current mode and down to previous mode\n")
2364 return rpki_exit(self
, vty
, argc
, argv
);
2367 DEFUNSH(VTYSH_BGPD
, bmp_exit
, bmp_exit_cmd
, "exit",
2368 "Exit current mode and down to previous mode\n")
2374 DEFUNSH(VTYSH_BGPD
, bmp_quit
, bmp_quit_cmd
, "quit",
2375 "Exit current mode and down to previous mode\n")
2377 return bmp_exit(self
, vty
, argc
, argv
);
2379 #endif /* HAVE_BGPD */
2381 DEFUNSH(VTYSH_VRF
, exit_vrf_config
, exit_vrf_config_cmd
, "exit-vrf",
2382 "Exit from VRF configuration mode\n")
2384 if (vty
->node
== VRF_NODE
)
2385 vty
->node
= CONFIG_NODE
;
2389 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_config
, exit_srv6_config_cmd
, "exit",
2390 "Exit from SRv6 configuration mode\n")
2392 if (vty
->node
== SRV6_NODE
)
2393 vty
->node
= SEGMENT_ROUTING_NODE
;
2397 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_locs_config
, exit_srv6_locs_config_cmd
, "exit",
2398 "Exit from SRv6-locator configuration mode\n")
2400 if (vty
->node
== SRV6_LOCS_NODE
)
2401 vty
->node
= SRV6_NODE
;
2405 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_loc_config
, exit_srv6_loc_config_cmd
, "exit",
2406 "Exit from SRv6-locators configuration mode\n")
2408 if (vty
->node
== SRV6_LOC_NODE
)
2409 vty
->node
= SRV6_LOCS_NODE
;
2414 DEFUNSH(VTYSH_RIPD
, vtysh_exit_ripd
, vtysh_exit_ripd_cmd
, "exit",
2415 "Exit current mode and down to previous mode\n")
2417 return vtysh_exit(vty
);
2420 DEFUNSH(VTYSH_RIPD
, vtysh_quit_ripd
, vtysh_quit_ripd_cmd
, "quit",
2421 "Exit current mode and down to previous mode\n")
2423 return vtysh_exit_ripd(self
, vty
, argc
, argv
);
2425 #endif /* HAVE_RIPD */
2428 DEFUNSH(VTYSH_RIPNGD
, vtysh_exit_ripngd
, vtysh_exit_ripngd_cmd
, "exit",
2429 "Exit current mode and down to previous mode\n")
2431 return vtysh_exit(vty
);
2434 DEFUNSH(VTYSH_RIPNGD
, vtysh_quit_ripngd
, vtysh_quit_ripngd_cmd
, "quit",
2435 "Exit current mode and down to previous mode\n")
2437 return vtysh_exit_ripngd(self
, vty
, argc
, argv
);
2439 #endif /* HAVE_RIPNGD */
2441 DEFUNSH(VTYSH_RMAP
, vtysh_exit_rmap
, vtysh_exit_rmap_cmd
, "exit",
2442 "Exit current mode and down to previous mode\n")
2444 return vtysh_exit(vty
);
2447 DEFUNSH(VTYSH_RMAP
, vtysh_quit_rmap
, vtysh_quit_rmap_cmd
, "quit",
2448 "Exit current mode and down to previous mode\n")
2450 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2454 DEFUNSH(VTYSH_PBRD
, vtysh_exit_pbr_map
, vtysh_exit_pbr_map_cmd
, "exit",
2455 "Exit current mode and down to previous mode\n")
2457 return vtysh_exit(vty
);
2460 DEFUNSH(VTYSH_PBRD
, vtysh_quit_pbr_map
, vtysh_quit_pbr_map_cmd
, "quit",
2461 "Exit current mode and down to previous mode\n")
2463 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2465 #endif /* HAVE_PBRD */
2468 DEFUNSH(VTYSH_BGPD
, vtysh_exit_bgpd
, vtysh_exit_bgpd_cmd
, "exit",
2469 "Exit current mode and down to previous mode\n")
2471 return vtysh_exit(vty
);
2474 DEFUNSH(VTYSH_BGPD
, vtysh_quit_bgpd
, vtysh_quit_bgpd_cmd
, "quit",
2475 "Exit current mode and down to previous mode\n")
2477 return vtysh_exit_bgpd(self
, vty
, argc
, argv
);
2479 #endif /* HAVE_BGPD */
2482 DEFUNSH(VTYSH_OSPFD
, vtysh_exit_ospfd
, vtysh_exit_ospfd_cmd
, "exit",
2483 "Exit current mode and down to previous mode\n")
2485 return vtysh_exit(vty
);
2488 DEFUNSH(VTYSH_OSPFD
, vtysh_quit_ospfd
, vtysh_quit_ospfd_cmd
, "quit",
2489 "Exit current mode and down to previous mode\n")
2491 return vtysh_exit_ospfd(self
, vty
, argc
, argv
);
2493 #endif /* HAVE_OSPFD */
2496 DEFUNSH(VTYSH_EIGRPD
, vtysh_exit_eigrpd
, vtysh_exit_eigrpd_cmd
, "exit",
2497 "Exit current mode and down to previous mode\n")
2499 return vtysh_exit(vty
);
2502 DEFUNSH(VTYSH_EIGRPD
, vtysh_quit_eigrpd
, vtysh_quit_eigrpd_cmd
, "quit",
2503 "Exit current mode and down to previous mode\n")
2505 return vtysh_exit(vty
);
2507 #endif /* HAVE_EIGRPD */
2510 DEFUNSH(VTYSH_BABELD
, vtysh_exit_babeld
, vtysh_exit_babeld_cmd
, "exit",
2511 "Exit current mode and down to previous mode\n")
2513 return vtysh_exit(vty
);
2516 DEFUNSH(VTYSH_BABELD
, vtysh_quit_babeld
, vtysh_quit_babeld_cmd
, "quit",
2517 "Exit current mode and down to previous mode\n")
2519 return vtysh_exit(vty
);
2521 #endif /* HAVE_BABELD */
2524 DEFUNSH(VTYSH_OSPF6D
, vtysh_exit_ospf6d
, vtysh_exit_ospf6d_cmd
, "exit",
2525 "Exit current mode and down to previous mode\n")
2527 return vtysh_exit(vty
);
2530 DEFUNSH(VTYSH_OSPF6D
, vtysh_quit_ospf6d
, vtysh_quit_ospf6d_cmd
, "quit",
2531 "Exit current mode and down to previous mode\n")
2533 return vtysh_exit_ospf6d(self
, vty
, argc
, argv
);
2535 #endif /* HAVE_OSPF6D */
2537 #if defined(HAVE_LDPD)
2538 DEFUNSH(VTYSH_LDPD
, vtysh_exit_ldpd
, vtysh_exit_ldpd_cmd
, "exit",
2539 "Exit current mode and down to previous mode\n")
2541 return vtysh_exit(vty
);
2544 ALIAS(vtysh_exit_ldpd
, vtysh_quit_ldpd_cmd
, "quit",
2545 "Exit current mode and down to previous mode\n")
2549 DEFUNSH(VTYSH_ISISD
, vtysh_exit_isisd
, vtysh_exit_isisd_cmd
, "exit",
2550 "Exit current mode and down to previous mode\n")
2552 return vtysh_exit(vty
);
2555 DEFUNSH(VTYSH_ISISD
, vtysh_quit_isisd
, vtysh_quit_isisd_cmd
, "quit",
2556 "Exit current mode and down to previous mode\n")
2558 return vtysh_exit_isisd(self
, vty
, argc
, argv
);
2560 #endif /* HAVE_ISISD */
2563 DEFUNSH(VTYSH_BFDD
, vtysh_exit_bfdd
, vtysh_exit_bfdd_cmd
, "exit",
2564 "Exit current mode and down to previous mode\n")
2566 return vtysh_exit(vty
);
2569 ALIAS(vtysh_exit_bfdd
, vtysh_quit_bfdd_cmd
, "quit",
2570 "Exit current mode and down to previous mode\n")
2574 DEFUNSH(VTYSH_FABRICD
, vtysh_exit_fabricd
, vtysh_exit_fabricd_cmd
, "exit",
2575 "Exit current mode and down to previous mode\n")
2577 return vtysh_exit(vty
);
2580 DEFUNSH(VTYSH_FABRICD
, vtysh_quit_fabricd
, vtysh_quit_fabricd_cmd
, "quit",
2581 "Exit current mode and down to previous mode\n")
2583 return vtysh_exit_fabricd(self
, vty
, argc
, argv
);
2585 #endif /* HAVE_FABRICD */
2587 DEFUNSH(VTYSH_KEYS
, vtysh_exit_keys
, vtysh_exit_keys_cmd
, "exit",
2588 "Exit current mode and down to previous mode\n")
2590 return vtysh_exit(vty
);
2593 DEFUNSH(VTYSH_KEYS
, vtysh_quit_keys
, vtysh_quit_keys_cmd
, "quit",
2594 "Exit current mode and down to previous mode\n")
2596 return vtysh_exit_keys(self
, vty
, argc
, argv
);
2599 DEFUNSH(VTYSH_SR
, vtysh_exit_sr
, vtysh_exit_sr_cmd
, "exit",
2600 "Exit current mode and down to previous mode\n")
2602 return vtysh_exit(vty
);
2605 DEFUNSH(VTYSH_SR
, vtysh_quit_sr
, vtysh_quit_sr_cmd
, "quit",
2606 "Exit current mode and down to previous mode\n")
2608 return vtysh_exit(vty
);
2611 #if defined(HAVE_PATHD)
2612 DEFUNSH(VTYSH_PATHD
, vtysh_exit_pathd
, vtysh_exit_pathd_cmd
, "exit",
2613 "Exit current mode and down to previous mode\n")
2615 return vtysh_exit(vty
);
2618 DEFUNSH(VTYSH_PATHD
, vtysh_quit_pathd
, vtysh_quit_pathd_cmd
, "quit",
2619 "Exit current mode and down to previous mode\n")
2621 return vtysh_exit_pathd(self
, vty
, argc
, argv
);
2623 #endif /* HAVE_PATHD */
2625 DEFUNSH(VTYSH_ALL
, vtysh_exit_line_vty
, vtysh_exit_line_vty_cmd
, "exit",
2626 "Exit current mode and down to previous mode\n")
2628 return vtysh_exit(vty
);
2631 DEFUNSH(VTYSH_ALL
, vtysh_quit_line_vty
, vtysh_quit_line_vty_cmd
, "quit",
2632 "Exit current mode and down to previous mode\n")
2634 return vtysh_exit_line_vty(self
, vty
, argc
, argv
);
2637 DEFUNSH(VTYSH_INTERFACE
, vtysh_interface
, vtysh_interface_cmd
,
2638 "interface IFNAME [vrf NAME]",
2639 "Select an interface to configure\n"
2640 "Interface's name\n" VRF_CMD_HELP_STR
)
2642 vty
->node
= INTERFACE_NODE
;
2646 DEFUNSH(VTYSH_ZEBRA
, vtysh_pseudowire
, vtysh_pseudowire_cmd
,
2647 "pseudowire IFNAME",
2648 "Static pseudowire configuration\n"
2649 "Pseudowire name\n")
2651 vty
->node
= PW_NODE
;
2655 DEFUNSH(VTYSH_NH_GROUP
,
2656 vtysh_nexthop_group
, vtysh_nexthop_group_cmd
,
2657 "nexthop-group NHGNAME",
2658 "Nexthop Group configuration\n"
2659 "Name of the Nexthop Group\n")
2661 vty
->node
= NH_GROUP_NODE
;
2665 DEFSH(VTYSH_NH_GROUP
, vtysh_no_nexthop_group_cmd
,
2666 "no nexthop-group NHGNAME",
2668 "Nexthop Group Configuration\n"
2669 "Name of the Nexthop Group\n")
2671 DEFUNSH(VTYSH_VRF
, vtysh_vrf
, vtysh_vrf_cmd
, "vrf NAME",
2672 "Select a VRF to configure\n"
2675 vty
->node
= VRF_NODE
;
2679 DEFUNSH(VTYSH_VRF
, vtysh_exit_vrf
, vtysh_exit_vrf_cmd
, "exit",
2680 "Exit current mode and down to previous mode\n")
2682 return vtysh_exit(vty
);
2685 DEFUNSH(VTYSH_VRF
, vtysh_quit_vrf
, vtysh_quit_vrf_cmd
, "quit",
2686 "Exit current mode and down to previous mode\n")
2688 return vtysh_exit_vrf(self
, vty
, argc
, argv
);
2691 DEFUNSH(VTYSH_NH_GROUP
,
2692 vtysh_exit_nexthop_group
, vtysh_exit_nexthop_group_cmd
,
2693 "exit", "Exit current mode and down to previous mode\n")
2695 return vtysh_exit(vty
);
2698 DEFUNSH(VTYSH_NH_GROUP
,
2699 vtysh_quit_nexthop_group
, vtysh_quit_nexthop_group_cmd
,
2700 "quit", "Exit current mode and down to previous mode\n")
2702 return vtysh_exit_nexthop_group(self
, vty
, argc
, argv
);
2705 DEFUNSH(VTYSH_INTERFACE
, vtysh_exit_interface
, vtysh_exit_interface_cmd
, "exit",
2706 "Exit current mode and down to previous mode\n")
2708 return vtysh_exit(vty
);
2711 DEFUNSH(VTYSH_INTERFACE
, vtysh_quit_interface
, vtysh_quit_interface_cmd
, "quit",
2712 "Exit current mode and down to previous mode\n")
2714 return vtysh_exit_interface(self
, vty
, argc
, argv
);
2717 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_pseudowire
, vtysh_exit_pseudowire_cmd
, "exit",
2718 "Exit current mode and down to previous mode\n")
2720 return vtysh_exit(vty
);
2723 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_pseudowire
, vtysh_quit_pseudowire_cmd
, "quit",
2724 "Exit current mode and down to previous mode\n")
2726 return vtysh_exit_pseudowire(self
, vty
, argc
, argv
);
2729 static char *do_prepend(struct vty
*vty
, struct cmd_token
**argv
, int argc
)
2731 const char *argstr
[argc
+ 1];
2734 if (vty
->node
!= VIEW_NODE
) {
2739 for (i
= 0; i
< argc
; i
++)
2740 argstr
[i
+ off
] = argv
[i
]->arg
;
2742 return frrstr_join(argstr
, argc
+ off
, " ");
2745 static int show_per_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2746 const char *headline
)
2749 int ret
= CMD_SUCCESS
;
2750 char *line
= do_prepend(vty
, argv
, argc
);
2752 for (i
= 0; i
< array_size(vtysh_client
); i
++)
2753 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
2754 vty_out(vty
, headline
, vtysh_client
[i
].name
);
2755 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
2759 XFREE(MTYPE_TMP
, line
);
2764 static int show_one_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2768 char *line
= do_prepend(vty
, argv
, argc
);
2770 ret
= vtysh_client_execute_name(name
, line
);
2772 XFREE(MTYPE_TMP
, line
);
2777 DEFUN (vtysh_show_poll
,
2778 vtysh_show_poll_cmd
,
2781 "Thread information\n"
2782 "Thread Poll Information\n")
2784 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2787 DEFUN (vtysh_show_thread
,
2788 vtysh_show_thread_cmd
,
2789 "show thread cpu [FILTER]",
2791 "Thread information\n"
2792 "Thread CPU usage\n"
2793 "Display filter (rwtexb)\n")
2795 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2798 DEFUN (vtysh_show_work_queues
,
2799 vtysh_show_work_queues_cmd
,
2802 "Work Queue information\n")
2804 return show_per_daemon(vty
, argv
, argc
,
2805 "Work queue statistics for %s:\n");
2808 DEFUN (vtysh_show_work_queues_daemon
,
2809 vtysh_show_work_queues_daemon_cmd
,
2810 "show work-queues " DAEMONS_LIST
,
2812 "Work Queue information\n"
2815 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2818 DEFUNSH(VTYSH_ZEBRA
, vtysh_link_params
, vtysh_link_params_cmd
, "link-params",
2821 vty
->node
= LINK_PARAMS_NODE
;
2825 DEFUNSH(VTYSH_ZEBRA
, exit_link_params
, exit_link_params_cmd
, "exit-link-params",
2826 "Exit from Link Params configuration node\n")
2828 if (vty
->node
== LINK_PARAMS_NODE
)
2829 vty
->node
= INTERFACE_NODE
;
2833 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_link_params
, vtysh_exit_link_params_cmd
, "exit",
2834 "Exit current mode and down to previous mode\n")
2836 if (vty
->node
== LINK_PARAMS_NODE
)
2837 vty
->node
= INTERFACE_NODE
;
2841 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_link_params
, vtysh_quit_link_params_cmd
, "quit",
2842 "Exit current mode and down to previous mode\n")
2844 return vtysh_exit_link_params(self
, vty
, argc
, argv
);
2847 DEFUNSH_HIDDEN (0x00,
2849 vtysh_debug_all_cmd
,
2853 "Toggle all debugs on or off\n")
2858 DEFUN (vtysh_show_debugging
,
2859 vtysh_show_debugging_cmd
,
2864 return show_per_daemon(vty
, argv
, argc
, "");
2867 DEFUN (vtysh_show_debugging_hashtable
,
2868 vtysh_show_debugging_hashtable_cmd
,
2869 "show debugging hashtable [statistics]",
2872 "Statistics about hash tables\n"
2873 "Statistics about hash tables\n")
2875 bool stats
= strmatch(argv
[argc
- 1]->text
, "statistics");
2879 "Load factor (LF) - average number of elements across all buckets\n");
2881 "Full load factor (FLF) - average number of elements across full buckets\n\n");
2883 "Standard deviation (SD) is calculated for both the LF and FLF\n");
2885 "and indicates the typical deviation of bucket chain length\n");
2886 vty_out(vty
, "from the value in the corresponding load factor.\n\n");
2888 return show_per_daemon(vty
, argv
, stats
? argc
- 1 : argc
,
2889 "Hashtable statistics for %s:\n");
2892 DEFUN (vtysh_show_error_code
,
2893 vtysh_show_error_code_cmd
,
2894 "show error <(1-4294967296)|all> [json]",
2896 "Information on errors\n"
2897 "Error code to get info about\n"
2898 "Information on all errors\n"
2903 if (!strmatch(argv
[2]->text
, "all"))
2904 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2906 /* If it's not a shared code, send it to all the daemons */
2907 if (arg
< LIB_FERR_START
|| arg
> LIB_FERR_END
) {
2908 show_per_daemon(vty
, argv
, argc
, "");
2909 /* Otherwise, print it ourselves to avoid duplication */
2911 bool json
= strmatch(argv
[argc
- 1]->text
, "json");
2913 if (!strmatch(argv
[2]->text
, "all"))
2914 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2916 log_ref_display(vty
, arg
, json
);
2923 DEFUN_HIDDEN (show_config_running
,
2924 show_config_running_cmd
,
2925 "show configuration running\
2926 [<json|xml> [translate WORD]]\
2927 [with-defaults]" DAEMONS_LIST
,
2929 "Configuration information\n"
2930 "Running configuration\n"
2931 "Change output format to JSON\n"
2932 "Change output format to XML\n"
2933 "Translate output\n"
2934 "YANG module translator\n"
2935 "Show default values\n"
2938 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2941 DEFUN (show_yang_operational_data
,
2942 show_yang_operational_data_cmd
,
2943 "show yang operational-data XPATH\
2949 "YANG information\n"
2950 "Show YANG operational data\n"
2951 "XPath expression specifying the YANG data path\n"
2952 "Set the output format\n"
2953 "JavaScript Object Notation\n"
2954 "Extensible Markup Language\n"
2955 "Translate operational data\n"
2956 "YANG module translator\n"
2959 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2962 DEFUN(show_yang_module
, show_yang_module_cmd
,
2963 "show yang module [module-translator WORD] " DAEMONS_LIST
,
2965 "YANG information\n"
2966 "Show loaded modules\n"
2967 "YANG module translator\n"
2968 "YANG module translator\n" DAEMONS_STR
)
2970 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2973 DEFUN(show_yang_module_detail
, show_yang_module_detail_cmd
,
2975 [module-translator WORD]\
2976 WORD <compiled|summary|tree|yang|yin> " DAEMONS_LIST
,
2978 "YANG information\n"
2979 "Show loaded modules\n"
2980 "YANG module translator\n"
2981 "YANG module translator\n"
2983 "Display compiled module in YANG format\n"
2984 "Display summary information about the module\n"
2985 "Display module in the tree (RFC 8340) format\n"
2986 "Display module in the YANG format\n"
2987 "Display module in the YIN format\n" DAEMONS_STR
)
2989 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2993 DEFUNSH(VTYSH_ALL
, debug_nb
,
2995 "[no] debug northbound\
2997 callbacks [{configuration|state|rpc}]\
3004 "Northbound debugging\n"
3011 "libyang debugging\n")
3016 DEFUN (vtysh_show_history
,
3017 vtysh_show_history_cmd
,
3020 "The list of commands stored in history\n")
3022 HIST_ENTRY
**hlist
= history_list();
3026 vty_out(vty
, "%s\n", hlist
[i
]->line
);
3033 DEFUN (vtysh_show_memory
,
3034 vtysh_show_memory_cmd
,
3035 "show memory [" DAEMONS_LIST
"]",
3037 "Memory statistics\n"
3041 return show_one_daemon(vty
, argv
, argc
- 1,
3042 argv
[argc
- 1]->text
);
3044 return show_per_daemon(vty
, argv
, argc
, "Memory statistics for %s:\n");
3047 DEFUN (vtysh_show_modules
,
3048 vtysh_show_modules_cmd
,
3053 return show_per_daemon(vty
, argv
, argc
, "Module information for %s:\n");
3056 /* Logging commands. */
3057 DEFUN (vtysh_show_logging
,
3058 vtysh_show_logging_cmd
,
3061 "Show current logging configuration\n")
3063 return show_per_daemon(vty
, argv
, argc
,
3064 "Logging configuration for %s:\n");
3067 DEFUNSH(VTYSH_ALL
, vtysh_debug_memstats
,
3068 vtysh_debug_memstats_cmd
, "[no] debug memstats-at-exit",
3071 "Print memory statistics at exit\n")
3076 DEFUN(vtysh_debug_uid_backtrace
,
3077 vtysh_debug_uid_backtrace_cmd
,
3078 "[no] debug unique-id UID backtrace",
3081 "Options per individual log message, by unique ID\n"
3082 "Log message unique ID (XXXXX-XXXXX)\n"
3083 "Add backtrace to log when message is printed\n")
3085 unsigned int i
, ok
= 0;
3086 int err
= CMD_SUCCESS
, ret
;
3090 if (!strcmp(argv
[0]->text
, "no")) {
3092 snprintfrr(line
, sizeof(line
),
3093 "no debug unique-id %s backtrace", uid
);
3096 snprintfrr(line
, sizeof(line
), "debug unique-id %s backtrace",
3100 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3101 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
3102 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3107 case CMD_ERR_NOTHING_TODO
:
3108 /* ignore this daemon
3110 * note this doesn't need to handle instances
3111 * of the same daemon individually because
3112 * the same daemon will have the same UIDs
3116 if (err
== CMD_SUCCESS
)
3122 if (err
== CMD_SUCCESS
&& !ok
) {
3123 vty_out(vty
, "%% no running daemon recognizes unique-ID %s\n",
3130 DEFUNSH(VTYSH_ALL
, vtysh_service_password_encrypt
,
3131 vtysh_service_password_encrypt_cmd
, "service password-encryption",
3132 "Set up miscellaneous service\n"
3133 "Enable encrypted passwords\n")
3138 DEFUNSH(VTYSH_ALL
, no_vtysh_service_password_encrypt
,
3139 no_vtysh_service_password_encrypt_cmd
, "no service password-encryption",
3141 "Set up miscellaneous service\n"
3142 "Enable encrypted passwords\n")
3147 DEFUNSH(VTYSH_ALL
, vtysh_config_password
, vtysh_password_cmd
,
3148 "password [(8-8)] LINE",
3149 "Modify the terminal connection password\n"
3150 "Specifies a HIDDEN password will follow\n"
3151 "The password string\n")
3156 DEFUNSH(VTYSH_ALL
, no_vtysh_config_password
, no_vtysh_password_cmd
,
3157 "no password", NO_STR
3158 "Modify the terminal connection password\n")
3160 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3165 DEFUNSH(VTYSH_ALL
, vtysh_config_enable_password
, vtysh_enable_password_cmd
,
3166 "enable password [(8-8)] LINE",
3167 "Modify enable password parameters\n"
3168 "Assign the privileged level password\n"
3169 "Specifies a HIDDEN password will follow\n"
3170 "The 'enable' password string\n")
3175 DEFUNSH(VTYSH_ALL
, no_vtysh_config_enable_password
,
3176 no_vtysh_enable_password_cmd
, "no enable password", NO_STR
3177 "Modify enable password parameters\n"
3178 "Assign the privileged level password\n")
3180 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3185 DEFUN (vtysh_write_terminal
,
3186 vtysh_write_terminal_cmd
,
3187 "write terminal ["DAEMONS_LIST
"] [no-header]",
3188 "Write running configuration to memory, network, or terminal\n"
3189 "Write to terminal\n"
3191 "Skip \"Building configuration...\" header\n")
3194 char line
[] = "do write terminal\n";
3196 if (!strcmp(argv
[argc
- 1]->arg
, "no-header"))
3199 vty_out(vty
, "Building configuration...\n");
3200 vty_out(vty
, "\nCurrent configuration:\n");
3201 vty_out(vty
, "!\n");
3204 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3206 || (strmatch(vtysh_client
[i
].name
, argv
[2]->text
)))
3207 vtysh_client_config(&vtysh_client
[i
], line
);
3209 /* Integrate vtysh specific configuration. */
3210 vty_open_pager(vty
);
3211 vtysh_config_write();
3212 vtysh_config_dump();
3213 vty_close_pager(vty
);
3214 vty_out(vty
, "end\n");
3219 DEFUN (vtysh_show_running_config
,
3220 vtysh_show_running_config_cmd
,
3221 "show running-config ["DAEMONS_LIST
"] [no-header]",
3223 "Current operating configuration\n"
3225 "Skip \"Building configuration...\" header\n")
3227 return vtysh_write_terminal(self
, vty
, argc
, argv
);
3230 DEFUN (vtysh_integrated_config
,
3231 vtysh_integrated_config_cmd
,
3232 "service integrated-vtysh-config",
3233 "Set up miscellaneous service\n"
3234 "Write configuration into integrated file\n")
3236 vtysh_write_integrated
= WRITE_INTEGRATED_YES
;
3240 DEFUN (no_vtysh_integrated_config
,
3241 no_vtysh_integrated_config_cmd
,
3242 "no service integrated-vtysh-config",
3244 "Set up miscellaneous service\n"
3245 "Write configuration into integrated file\n")
3247 vtysh_write_integrated
= WRITE_INTEGRATED_NO
;
3251 static void backup_config_file(const char *fbackup
)
3253 char *integrate_sav
= NULL
;
3255 size_t integrate_sav_sz
= strlen(fbackup
) + strlen(CONF_BACKUP_EXT
) + 1;
3256 integrate_sav
= malloc(integrate_sav_sz
);
3257 strlcpy(integrate_sav
, fbackup
, integrate_sav_sz
);
3258 strlcat(integrate_sav
, CONF_BACKUP_EXT
, integrate_sav_sz
);
3260 /* Move current configuration file to backup config file. */
3261 if (unlink(integrate_sav
) != 0 && errno
!= ENOENT
)
3262 vty_out(vty
, "Unlink failed for %s: %s\n", integrate_sav
,
3264 if (rename(fbackup
, integrate_sav
) != 0 && errno
!= ENOENT
)
3265 vty_out(vty
, "Error renaming %s to %s: %s\n", fbackup
,
3266 integrate_sav
, strerror(errno
));
3267 free(integrate_sav
);
3270 int vtysh_write_config_integrated(void)
3273 char line
[] = "do write terminal\n";
3277 struct passwd
*pwentry
;
3280 struct group
*grentry
;
3287 vty_out(vty
, "Building Configuration...\n");
3289 backup_config_file(frr_config
);
3290 fp
= fopen(frr_config
, "w");
3293 "%% Error: failed to open configuration file %s: %s\n",
3294 frr_config
, safe_strerror(errno
));
3295 return CMD_WARNING_CONFIG_FAILED
;
3299 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3300 vtysh_client_config(&vtysh_client
[i
], line
);
3302 vtysh_config_write();
3303 vty
->of_saved
= vty
->of
;
3305 vtysh_config_dump();
3306 vty
->of
= vty
->of_saved
;
3308 if (fchmod(fd
, CONFIGFILE_MASK
) != 0) {
3309 printf("%% Warning: can't chmod configuration file %s: %s\n",
3310 frr_config
, safe_strerror(errno
));
3315 pwentry
= getpwnam(FRR_USER
);
3317 uid
= pwentry
->pw_uid
;
3319 printf("%% Warning: could not look up user \"%s\"\n", FRR_USER
);
3324 grentry
= getgrnam(FRR_GROUP
);
3326 gid
= grentry
->gr_gid
;
3328 printf("%% Warning: could not look up group \"%s\"\n",
3334 if (!fstat(fd
, &st
)) {
3335 if (st
.st_uid
== uid
)
3337 if (st
.st_gid
== gid
)
3339 if ((uid
!= (uid_t
)-1 || gid
!= (gid_t
)-1)
3340 && fchown(fd
, uid
, gid
)) {
3341 printf("%% Warning: can't chown configuration file %s: %s\n",
3342 frr_config
, safe_strerror(errno
));
3346 printf("%% Warning: stat() failed on %s: %s\n", frr_config
,
3347 safe_strerror(errno
));
3353 printf("Integrated configuration saved to %s\n", frr_config
);
3361 static bool want_config_integrated(void)
3365 switch (vtysh_write_integrated
) {
3366 case WRITE_INTEGRATED_UNSPECIFIED
:
3367 if (stat(frr_config
, &s
) && errno
== ENOENT
)
3370 case WRITE_INTEGRATED_NO
:
3372 case WRITE_INTEGRATED_YES
:
3378 DEFUN (vtysh_write_memory
,
3379 vtysh_write_memory_cmd
,
3380 "write [<memory|file>]",
3381 "Write running configuration to memory, network, or terminal\n"
3382 "Write configuration to the file (same as write file)\n"
3383 "Write configuration to the file (same as write memory)\n")
3385 int ret
= CMD_SUCCESS
;
3386 char line
[] = "do write memory\n";
3389 vty_out(vty
, "Note: this version of vtysh never writes vtysh.conf\n");
3391 /* If integrated frr.conf explicitely set. */
3392 if (want_config_integrated()) {
3393 ret
= CMD_WARNING_CONFIG_FAILED
;
3395 /* first attempt to use watchfrr if it's available */
3396 bool used_watchfrr
= false;
3398 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3399 if (vtysh_client
[i
].flag
== VTYSH_WATCHFRR
)
3401 if (i
< array_size(vtysh_client
) && vtysh_client
[i
].fd
!= -1) {
3402 used_watchfrr
= true;
3403 ret
= vtysh_client_execute(&vtysh_client
[i
],
3404 "do write integrated");
3408 * If we didn't use watchfrr, fallback to writing the config
3411 if (!used_watchfrr
) {
3412 printf("\nWarning: attempting direct configuration write without watchfrr.\nFile permissions and ownership may be incorrect, or write may fail.\n\n");
3413 ret
= vtysh_write_config_integrated();
3418 vty_out(vty
, "Building Configuration...\n");
3420 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3421 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3426 DEFUN (vtysh_copy_running_config
,
3427 vtysh_copy_running_config_cmd
,
3428 "copy running-config startup-config",
3429 "Copy from one file to another\n"
3430 "Copy from current system configuration\n"
3431 "Copy to startup configuration\n")
3433 return vtysh_write_memory(self
, vty
, argc
, argv
);
3436 DEFUN (vtysh_copy_to_running
,
3437 vtysh_copy_to_running_cmd
,
3438 "copy FILENAME running-config",
3439 "Apply a configuration file\n"
3440 "Configuration file to read\n"
3441 "Apply to current configuration\n")
3444 const char *fname
= argv
[1]->arg
;
3446 ret
= vtysh_read_config(fname
, true);
3448 /* Return to enable mode - the 'read_config' api leaves us up a level */
3449 vtysh_execute_no_pager("enable");
3454 DEFUN (vtysh_terminal_paginate
,
3455 vtysh_terminal_paginate_cmd
,
3456 "[no] terminal paginate",
3458 "Set terminal line parameters\n"
3459 "Use pager for output scrolling\n")
3461 free(vtysh_pager_name
);
3462 vtysh_pager_name
= NULL
;
3464 if (strcmp(argv
[0]->text
, "no"))
3465 vtysh_pager_envdef(true);
3469 DEFUN (vtysh_terminal_length
,
3470 vtysh_terminal_length_cmd
,
3471 "[no] terminal length (0-4294967295)",
3473 "Set terminal line parameters\n"
3474 "Set number of lines on a screen\n"
3475 "Number of lines on screen (0 for no pausing, nonzero to use pager)\n")
3478 unsigned long lines
;
3480 free(vtysh_pager_name
);
3481 vtysh_pager_name
= NULL
;
3483 if (!strcmp(argv
[0]->text
, "no") || !strcmp(argv
[1]->text
, "no")) {
3484 /* "terminal no length" = use VTYSH_PAGER */
3485 vtysh_pager_envdef(true);
3489 lines
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
3492 "%% The \"terminal length\" command is deprecated and its value is ignored.\n"
3493 "%% Please use \"terminal paginate\" instead with OS TTY length handling.\n");
3494 vtysh_pager_envdef(true);
3500 ALIAS_DEPRECATED(vtysh_terminal_length
,
3501 vtysh_terminal_no_length_cmd
,
3502 "terminal no length",
3503 "Set terminal line parameters\n"
3505 "Set number of lines on a screen\n")
3507 DEFUN (vtysh_show_daemons
,
3508 vtysh_show_daemons_cmd
,
3511 "Show list of running daemons\n")
3515 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3516 if (vtysh_client
[i
].fd
>= 0)
3517 vty_out(vty
, " %s", vtysh_client
[i
].name
);
3523 struct visual_prio
{
3524 /* 4 characters for nice alignment */
3527 int c256_background
;
3531 /* clang-format off */
3532 struct visual_prio visual_prios
[] = {
3534 .label
= "\e[31;1mEMRG",
3535 .c256_background
= 53,
3536 .c256_formatarg
= 225,
3539 .label
= "\e[31;1mALRT",
3540 .c256_background
= 53,
3541 .c256_formatarg
= 225,
3544 .label
= "\e[31;1mCRIT",
3545 .c256_background
= 53,
3546 .c256_formatarg
= 225,
3549 .label
= "\e[38;5;202mERR!",
3550 .c256_background
= 52,
3551 .c256_formatarg
= 224,
3554 .label
= "\e[38;5;222mWARN",
3555 .c256_background
= 58,
3556 .c256_formatarg
= 230,
3560 .c256_background
= 234,
3561 .c256_formatarg
= 195,
3564 .label
= "\e[38;5;192mINFO",
3565 .c256_background
= 236,
3566 .c256_formatarg
= 195,
3569 .label
= "\e[38;5;116mDEBG",
3570 .c256_background
= 238,
3571 .c256_formatarg
= 195,
3574 /* clang-format on */
3576 static void vtysh_log_print(struct vtysh_client
*vclient
,
3577 struct zlog_live_hdr
*hdr
, const char *text
)
3579 size_t textlen
= hdr
->textlen
, textpos
= 0;
3580 time_t ts
= hdr
->ts_sec
;
3581 struct visual_prio
*vis
;
3585 if (hdr
->prio
> array_size(visual_prios
))
3586 vis
= &visual_prios
[LOG_CRIT
];
3588 vis
= &visual_prios
[hdr
->prio
];
3590 localtime_r(&ts
, &tm
);
3591 strftime(ts_buf
, sizeof(ts_buf
), "%Y-%m-%d %H:%M:%S", &tm
);
3594 const char *label
= vis
->label
+ strlen(vis
->label
) - 4;
3596 fprintf(stderr
, "%s.%03u [%s] %s: %.*s\n", ts_buf
,
3597 hdr
->ts_nsec
/ 1000000U, label
, vclient
->name
,
3598 (int)textlen
, text
);
3603 "\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",
3604 vis
->c256_background
, ts_buf
, hdr
->ts_nsec
/ 1000000U,
3605 vis
->label
, vclient
->name
);
3607 for (size_t fmtpos
= 0; fmtpos
< hdr
->n_argpos
; fmtpos
++) {
3608 struct fmt_outpos
*fmt
= &hdr
->argpos
[fmtpos
];
3610 if (fmt
->off_start
< textpos
|| fmt
->off_end
< fmt
->off_start
||
3611 fmt
->off_end
> textlen
)
3614 while (fmt
->off_end
> fmt
->off_start
&&
3615 text
[fmt
->off_end
- 1] == ' ')
3618 fprintf(stderr
, "%.*s\e[38;5;%dm%.*s\e[38;5;251m",
3619 (int)(fmt
->off_start
- textpos
), text
+ textpos
,
3620 vis
->c256_formatarg
,
3621 (int)(fmt
->off_end
- fmt
->off_start
),
3622 text
+ fmt
->off_start
);
3623 textpos
= fmt
->off_end
;
3625 fprintf(stderr
, "%.*s\033[K\033[m\n", (int)(textlen
- textpos
),
3629 static void vtysh_log_read(struct thread
*thread
)
3631 struct vtysh_client
*vclient
= THREAD_ARG(thread
);
3633 struct zlog_live_hdr hdr
;
3639 thread_add_read(master
, vtysh_log_read
, vclient
, vclient
->log_fd
,
3640 &vclient
->log_reader
);
3642 ret
= recv(vclient
->log_fd
, &buf
, sizeof(buf
), 0);
3644 if (ret
< 0 && ERRNO_IO_RETRY(errno
))
3651 snprintfrr(buf
.text
, sizeof(buf
.text
),
3652 "log monitor connection error: %m");
3655 buf
.text
, sizeof(buf
.text
),
3656 "log monitor connection closed unexpectedly");
3657 buf
.hdr
.textlen
= strlen(buf
.text
);
3659 THREAD_OFF(vclient
->log_reader
);
3660 close(vclient
->log_fd
);
3661 vclient
->log_fd
= -1;
3663 clock_gettime(CLOCK_REALTIME
, &ts
);
3664 buf
.hdr
.ts_sec
= ts
.tv_sec
;
3665 buf
.hdr
.ts_nsec
= ts
.tv_nsec
;
3666 buf
.hdr
.prio
= LOG_ERR
;
3668 buf
.hdr
.arghdrlen
= 0;
3669 buf
.hdr
.n_argpos
= 0;
3672 if (stderr_stdout_same
) {
3673 #ifdef HAVE_RL_CLEAR_VISIBLE_LINE
3674 rl_clear_visible_line();
3681 text
= buf
.text
+ sizeof(buf
.hdr
.argpos
[0]) * buf
.hdr
.n_argpos
;
3682 vtysh_log_print(vclient
, &buf
.hdr
, text
);
3684 if (stderr_stdout_same
)
3685 rl_forced_update_display();
3691 /* clippy/clidef can't process the DEFPY below without some value for this */
3692 #define DAEMONS_LIST "daemon"
3695 DEFPY (vtysh_terminal_monitor
,
3696 vtysh_terminal_monitor_cmd
,
3697 "terminal monitor ["DAEMONS_LIST
"]$daemon",
3698 "Set terminal line parameters\n"
3699 "Receive log messages to active VTY session\n"
3702 static const char line
[] = "terminal monitor\n";
3703 int ret_all
= CMD_SUCCESS
, ret
, fd
;
3706 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3707 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3709 if (daemon
&& strcmp(vclient
->name
, daemon
))
3712 for (; vclient
; vclient
= vclient
->next
) {
3713 if (vclient
->log_fd
!= -1) {
3714 vty_out(vty
, "%% %s: already monitoring logs\n",
3721 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, &fd
);
3723 set_nonblocking(fd
);
3724 vclient
->log_fd
= fd
;
3725 thread_add_read(master
, vtysh_log_read
, vclient
,
3727 &vclient
->log_reader
);
3729 if (ret
!= CMD_SUCCESS
) {
3730 vty_out(vty
, "%% failed to enable logs on %s\n",
3732 ret_all
= CMD_WARNING
;
3738 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3740 "%% command had no effect, relevant daemons not connected?\n");
3741 ret_all
= CMD_WARNING
;
3746 DEFPY (no_vtysh_terminal_monitor
,
3747 no_vtysh_terminal_monitor_cmd
,
3748 "no terminal monitor ["DAEMONS_LIST
"]$daemon",
3750 "Set terminal line parameters\n"
3751 "Receive log messages to active VTY session\n"
3754 static const char line
[] = "no terminal monitor\n";
3755 int ret_all
= CMD_SUCCESS
, ret
;
3758 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3759 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3761 if (daemon
&& strcmp(vclient
->name
, daemon
))
3764 for (; vclient
; vclient
= vclient
->next
) {
3765 /* run this even if log_fd == -1, in case something
3768 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, NULL
);
3769 if (ret
!= CMD_SUCCESS
) {
3771 "%% failed to disable logs on %s\n",
3773 ret_all
= CMD_WARNING
;
3777 /* with this being a datagram socket, we can't expect
3778 * a close notification...
3780 if (vclient
->log_fd
!= -1) {
3781 THREAD_OFF(vclient
->log_reader
);
3783 close(vclient
->log_fd
);
3784 vclient
->log_fd
= -1;
3789 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3791 "%% command had no effect, relevant daemons not connected?\n");
3792 ret_all
= CMD_WARNING
;
3798 /* Execute command in child process. */
3799 static void execute_command(const char *command
, int argc
, const char *arg1
,
3809 /* Failure of fork(). */
3810 fprintf(stderr
, "Can't fork: %s\n", safe_strerror(errno
));
3812 } else if (pid
== 0) {
3813 /* This is child process. */
3816 execlp(command
, command
, (const char *)NULL
);
3819 execlp(command
, command
, arg1
, (const char *)NULL
);
3822 execlp(command
, command
, arg1
, arg2
,
3823 (const char *)NULL
);
3827 /* When execlp suceed, this part is not executed. */
3828 fprintf(stderr
, "Can't execute %s: %s\n", command
,
3829 safe_strerror(errno
));
3832 /* This is parent. */
3834 wait4(pid
, &status
, 0, NULL
);
3842 "Send echo messages\n"
3843 "Ping destination address or hostname\n")
3847 argv_find(argv
, argc
, "WORD", &idx
);
3848 execute_command("ping", 1, argv
[idx
]->arg
, NULL
);
3852 ALIAS(vtysh_ping
, vtysh_ping_ip_cmd
, "ping ip WORD",
3853 "Send echo messages\n"
3855 "Ping destination address or hostname\n")
3857 DEFUN (vtysh_traceroute
,
3858 vtysh_traceroute_cmd
,
3860 "Trace route to destination\n"
3861 "Trace route to destination address or hostname\n")
3865 argv_find(argv
, argc
, "WORD", &idx
);
3866 execute_command("traceroute", 1, argv
[idx
]->arg
, NULL
);
3870 ALIAS(vtysh_traceroute
, vtysh_traceroute_ip_cmd
, "traceroute ip WORD",
3871 "Trace route to destination\n"
3873 "Trace route to destination address or hostname\n")
3875 DEFUN (vtysh_mtrace
,
3877 "mtrace WORD [WORD]",
3878 "Multicast trace route to multicast source\n"
3879 "Multicast trace route to multicast source address\n"
3880 "Multicast trace route for multicast group address\n")
3883 execute_command("mtracebis", 1, argv
[1]->arg
, NULL
);
3885 execute_command("mtracebis", 2, argv
[1]->arg
, argv
[2]->arg
);
3892 "Send echo messages\n"
3894 "Ping destination address or hostname\n")
3896 execute_command("ping6", 1, argv
[2]->arg
, NULL
);
3900 DEFUN (vtysh_traceroute6
,
3901 vtysh_traceroute6_cmd
,
3902 "traceroute ipv6 WORD",
3903 "Trace route to destination\n"
3905 "Trace route to destination address or hostname\n")
3907 execute_command("traceroute6", 1, argv
[2]->arg
, NULL
);
3911 #if defined(HAVE_SHELL_ACCESS)
3912 DEFUN (vtysh_telnet
,
3915 "Open a telnet connection\n"
3916 "IP address or hostname of a remote system\n")
3918 execute_command("telnet", 1, argv
[1]->arg
, NULL
);
3922 DEFUN (vtysh_telnet_port
,
3923 vtysh_telnet_port_cmd
,
3925 "Open a telnet connection\n"
3926 "IP address or hostname of a remote system\n"
3927 "TCP Port number\n")
3929 execute_command("telnet", 2, argv
[1]->arg
, argv
[2]->arg
);
3936 "Open an ssh connection\n"
3939 execute_command("ssh", 1, argv
[1]->arg
, NULL
);
3943 DEFUN (vtysh_start_shell
,
3944 vtysh_start_shell_cmd
,
3946 "Start UNIX shell\n")
3948 execute_command("sh", 0, NULL
, NULL
);
3952 DEFUN (vtysh_start_bash
,
3953 vtysh_start_bash_cmd
,
3955 "Start UNIX shell\n"
3958 execute_command("bash", 0, NULL
, NULL
);
3962 DEFUN (vtysh_start_zsh
,
3963 vtysh_start_zsh_cmd
,
3965 "Start UNIX shell\n"
3968 execute_command("zsh", 0, NULL
, NULL
);
3975 "list [permutations]",
3976 "Print command list\n"
3977 "Print all possible command permutations\n")
3979 return cmd_list_cmds(vty
, argc
== 2);
3982 DEFUN (vtysh_output_file
,
3983 vtysh_output_file_cmd
,
3985 "Direct vtysh output to file\n"
3986 "Direct vtysh output to file\n"
3987 "Path to dump output to\n")
3989 const char *path
= argv
[argc
- 1]->arg
;
3990 vty
->of
= fopen(path
, "a");
3992 vty_out(vty
, "Failed to open file '%s': %s\n", path
,
3993 safe_strerror(errno
));
3999 DEFUN (no_vtysh_output_file
,
4000 no_vtysh_output_file_cmd
,
4001 "no output file [FILE]",
4003 "Direct vtysh output to file\n"
4004 "Direct vtysh output to file\n"
4005 "Path to dump output to\n")
4007 if (vty
->of
!= stdout
) {
4017 "Find CLI command matching a regular expression\n"
4018 "Search pattern (POSIX regex)\n")
4020 return cmd_find_cmds(vty
, argv
, argc
);
4023 DEFUN_HIDDEN(show_cli_graph_vtysh
,
4024 show_cli_graph_vtysh_cmd
,
4028 "Dump current command space as DOT graph\n")
4030 struct cmd_node
*cn
= vector_slot(cmdvec
, vty
->node
);
4031 char *dot
= cmd_graph_dump_dot(cn
->cmdgraph
);
4033 vty_out(vty
, "%s\n", dot
);
4034 XFREE(MTYPE_TMP
, dot
);
4038 static void vtysh_install_default(enum node_type node
)
4040 _install_element(node
, &config_list_cmd
);
4041 _install_element(node
, &find_cmd
);
4042 _install_element(node
, &show_cli_graph_vtysh_cmd
);
4043 _install_element(node
, &vtysh_output_file_cmd
);
4044 _install_element(node
, &no_vtysh_output_file_cmd
);
4047 /* Making connection to protocol daemon. */
4048 static int vtysh_connect(struct vtysh_client
*vclient
)
4052 struct sockaddr_un addr
;
4056 if (!vclient
->path
[0])
4057 snprintf(vclient
->path
, sizeof(vclient
->path
), "%s/%s.vty",
4058 vtydir
, vclient
->name
);
4059 path
= vclient
->path
;
4061 /* Stat socket to see if we have permission to access it. */
4062 ret
= stat(path
, &s_stat
);
4063 if (ret
< 0 && errno
!= ENOENT
) {
4064 fprintf(stderr
, "vtysh_connect(%s): stat = %s\n", path
,
4065 safe_strerror(errno
));
4070 if (!S_ISSOCK(s_stat
.st_mode
)) {
4071 fprintf(stderr
, "vtysh_connect(%s): Not a socket\n",
4077 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
4080 fprintf(stderr
, "vtysh_connect(%s): socket = %s\n", path
,
4081 safe_strerror(errno
));
4086 memset(&addr
, 0, sizeof(struct sockaddr_un
));
4087 addr
.sun_family
= AF_UNIX
;
4088 strlcpy(addr
.sun_path
, path
, sizeof(addr
.sun_path
));
4089 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
4090 len
= addr
.sun_len
= SUN_LEN(&addr
);
4092 len
= sizeof(addr
.sun_family
) + strlen(addr
.sun_path
);
4093 #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
4095 ret
= connect(sock
, (struct sockaddr
*)&addr
, len
);
4098 fprintf(stderr
, "vtysh_connect(%s): connect = %s\n", path
,
4099 safe_strerror(errno
));
4109 static int vtysh_reconnect(struct vtysh_client
*vclient
)
4113 fprintf(stderr
, "Warning: connecting to %s...", vclient
->name
);
4114 ret
= vtysh_connect(vclient
);
4116 fprintf(stderr
, "failed!\n");
4119 fprintf(stderr
, "success!\n");
4120 if (vtysh_client_execute(vclient
, "enable") < 0)
4122 return vtysh_execute_no_pager("end");
4125 /* Return true if str ends with suffix, else return false */
4126 static int ends_with(const char *str
, const char *suffix
)
4128 if (!str
|| !suffix
)
4130 size_t lenstr
= strlen(str
);
4131 size_t lensuffix
= strlen(suffix
);
4132 if (lensuffix
> lenstr
)
4134 return strncmp(str
+ lenstr
- lensuffix
, suffix
, lensuffix
) == 0;
4137 static void vtysh_client_sorted_insert(struct vtysh_client
*head_client
,
4138 struct vtysh_client
*client
)
4140 struct vtysh_client
*prev_node
, *current_node
;
4142 prev_node
= head_client
;
4143 current_node
= head_client
->next
;
4144 while (current_node
) {
4145 if (strcmp(current_node
->path
, client
->path
) > 0)
4148 prev_node
= current_node
;
4149 current_node
= current_node
->next
;
4151 client
->next
= current_node
;
4152 prev_node
->next
= client
;
4155 #define MAXIMUM_INSTANCES 10
4157 static void vtysh_update_all_instances(struct vtysh_client
*head_client
)
4159 struct vtysh_client
*client
;
4161 struct dirent
*file
;
4164 if (head_client
->flag
!= VTYSH_OSPFD
)
4167 /* ls vty_sock_dir and look for all files ending in .vty */
4168 dir
= opendir(vtydir
);
4170 while ((file
= readdir(dir
)) != NULL
) {
4171 if (frrstr_startswith(file
->d_name
, "ospfd-")
4172 && ends_with(file
->d_name
, ".vty")) {
4173 if (n
== MAXIMUM_INSTANCES
) {
4175 "Parsing %s, client limit(%d) reached!\n",
4179 client
= (struct vtysh_client
*)malloc(
4180 sizeof(struct vtysh_client
));
4182 client
->name
= "ospfd";
4183 client
->flag
= VTYSH_OSPFD
;
4184 snprintf(client
->path
, sizeof(client
->path
),
4185 "%s/%s", vtydir
, file
->d_name
);
4186 client
->next
= NULL
;
4187 vtysh_client_sorted_insert(head_client
, client
);
4195 static int vtysh_connect_all_instances(struct vtysh_client
*head_client
)
4197 struct vtysh_client
*client
;
4200 vtysh_update_all_instances(head_client
);
4202 client
= head_client
->next
;
4204 if (vtysh_connect(client
) == 0)
4206 client
= client
->next
;
4212 int vtysh_connect_all(const char *daemon_name
)
4218 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
4220 || !strcmp(daemon_name
, vtysh_client
[i
].name
)) {
4222 if (vtysh_connect(&vtysh_client
[i
]) == 0)
4225 rc
+= vtysh_connect_all_instances(&vtysh_client
[i
]);
4229 fprintf(stderr
, "Error: no daemons match name %s!\n",
4234 /* To disable readline's filename completion. */
4235 static char *vtysh_completion_entry_function(const char *ignore
,
4241 void vtysh_readline_init(void)
4243 /* readline related settings. */
4244 char *disable_bracketed_paste
=
4245 XSTRDUP(MTYPE_TMP
, "set enable-bracketed-paste off");
4248 rl_parse_and_bind(disable_bracketed_paste
);
4249 rl_bind_key('?', (rl_command_func_t
*)vtysh_rl_describe
);
4250 rl_completion_entry_function
= vtysh_completion_entry_function
;
4251 rl_attempted_completion_function
= new_completion
;
4253 XFREE(MTYPE_TMP
, disable_bracketed_paste
);
4256 char *vtysh_prompt(void)
4258 static char buf
[512];
4260 snprintf(buf
, sizeof(buf
), cmd_prompt(vty
->node
), cmd_hostname_get());
4264 static void vtysh_ac_line(void *arg
, const char *line
)
4268 for (i
= 0; i
< vector_active(comps
); i
++)
4269 if (!strcmp(line
, (char *)vector_slot(comps
, i
)))
4271 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, line
));
4274 static void vtysh_autocomplete(vector comps
, struct cmd_token
*token
)
4279 snprintf(accmd
, sizeof(accmd
), "autocomplete %d %s %s", token
->type
,
4280 token
->text
, token
->varname
? token
->varname
: "-");
4282 vty
->of_saved
= vty
->of
;
4284 for (i
= 0; i
< array_size(vtysh_client
); i
++)
4285 vtysh_client_run_all(&vtysh_client
[i
], accmd
, 1, vtysh_ac_line
,
4287 vty
->of
= vty
->of_saved
;
4290 static const struct cmd_variable_handler vtysh_var_handler
[] = {
4294 .completions
= vtysh_autocomplete
},
4295 {.completions
= NULL
}};
4297 void vtysh_uninit(void)
4299 if (vty
->of
!= stdout
)
4303 void vtysh_init_vty(void)
4305 struct stat st_out
, st_err
;
4307 cmd_defer_tree(true);
4309 for (size_t i
= 0; i
< array_size(vtysh_client
); i
++) {
4310 vtysh_client
[i
].fd
= -1;
4311 vtysh_client
[i
].log_fd
= -1;
4314 stderr_tty
= isatty(STDERR_FILENO
);
4316 if (fstat(STDOUT_FILENO
, &st_out
) || fstat(STDERR_FILENO
, &st_err
) ||
4317 (st_out
.st_dev
== st_err
.st_dev
&& st_out
.st_ino
== st_err
.st_ino
))
4318 stderr_stdout_same
= true;
4320 /* Make vty structure. */
4322 vty
->type
= VTY_SHELL
;
4323 vty
->node
= VIEW_NODE
;
4325 /* set default output */
4327 vtysh_pager_envdef(false);
4329 /* Initialize commands. */
4331 cmd_variable_handler_register(vtysh_var_handler
);
4335 install_node(&bgp_node
);
4336 install_element(CONFIG_NODE
, &router_bgp_cmd
);
4337 install_element(BGP_NODE
, &vtysh_exit_bgpd_cmd
);
4338 install_element(BGP_NODE
, &vtysh_quit_bgpd_cmd
);
4339 install_element(BGP_NODE
, &vtysh_end_all_cmd
);
4341 install_node(&bgp_vpnv4_node
);
4342 install_element(BGP_NODE
, &address_family_ipv4_vpn_cmd
);
4343 #ifdef KEEP_OLD_VPN_COMMANDS
4344 install_element(BGP_NODE
, &address_family_vpnv4_cmd
);
4345 #endif /* KEEP_OLD_VPN_COMMANDS */
4346 install_element(BGP_VPNV4_NODE
, &vtysh_exit_bgpd_cmd
);
4347 install_element(BGP_VPNV4_NODE
, &vtysh_quit_bgpd_cmd
);
4348 install_element(BGP_VPNV4_NODE
, &vtysh_end_all_cmd
);
4349 install_element(BGP_VPNV4_NODE
, &exit_address_family_cmd
);
4351 install_node(&bgp_vpnv6_node
);
4352 install_element(BGP_NODE
, &address_family_ipv6_vpn_cmd
);
4353 #ifdef KEEP_OLD_VPN_COMMANDS
4354 install_element(BGP_NODE
, &address_family_vpnv6_cmd
);
4355 #endif /* KEEP_OLD_VPN_COMMANDS */
4356 install_element(BGP_VPNV6_NODE
, &vtysh_exit_bgpd_cmd
);
4357 install_element(BGP_VPNV6_NODE
, &vtysh_quit_bgpd_cmd
);
4358 install_element(BGP_VPNV6_NODE
, &vtysh_end_all_cmd
);
4359 install_element(BGP_VPNV6_NODE
, &exit_address_family_cmd
);
4361 install_node(&bgp_flowspecv4_node
);
4362 install_element(BGP_NODE
, &address_family_flowspecv4_cmd
);
4363 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_exit_bgpd_cmd
);
4364 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_quit_bgpd_cmd
);
4365 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_end_all_cmd
);
4366 install_element(BGP_FLOWSPECV4_NODE
, &exit_address_family_cmd
);
4368 install_node(&bgp_flowspecv6_node
);
4369 install_element(BGP_NODE
, &address_family_flowspecv6_cmd
);
4370 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_exit_bgpd_cmd
);
4371 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_quit_bgpd_cmd
);
4372 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_end_all_cmd
);
4373 install_element(BGP_FLOWSPECV6_NODE
, &exit_address_family_cmd
);
4375 install_node(&bgp_ipv4_node
);
4376 install_element(BGP_NODE
, &address_family_ipv4_cmd
);
4377 install_element(BGP_IPV4_NODE
, &vtysh_exit_bgpd_cmd
);
4378 install_element(BGP_IPV4_NODE
, &vtysh_quit_bgpd_cmd
);
4379 install_element(BGP_IPV4_NODE
, &vtysh_end_all_cmd
);
4380 install_element(BGP_IPV4_NODE
, &exit_address_family_cmd
);
4382 install_node(&bgp_ipv4m_node
);
4383 install_element(BGP_NODE
, &address_family_ipv4_multicast_cmd
);
4384 install_element(BGP_IPV4M_NODE
, &vtysh_exit_bgpd_cmd
);
4385 install_element(BGP_IPV4M_NODE
, &vtysh_quit_bgpd_cmd
);
4386 install_element(BGP_IPV4M_NODE
, &vtysh_end_all_cmd
);
4387 install_element(BGP_IPV4M_NODE
, &exit_address_family_cmd
);
4389 install_node(&bgp_ipv4l_node
);
4390 install_element(BGP_NODE
, &address_family_ipv4_labeled_unicast_cmd
);
4391 install_element(BGP_IPV4L_NODE
, &vtysh_exit_bgpd_cmd
);
4392 install_element(BGP_IPV4L_NODE
, &vtysh_quit_bgpd_cmd
);
4393 install_element(BGP_IPV4L_NODE
, &vtysh_end_all_cmd
);
4394 install_element(BGP_IPV4L_NODE
, &exit_address_family_cmd
);
4396 install_node(&bgp_ipv6_node
);
4397 install_element(BGP_NODE
, &address_family_ipv6_cmd
);
4398 install_element(BGP_IPV6_NODE
, &vtysh_exit_bgpd_cmd
);
4399 install_element(BGP_IPV6_NODE
, &vtysh_quit_bgpd_cmd
);
4400 install_element(BGP_IPV6_NODE
, &vtysh_end_all_cmd
);
4401 install_element(BGP_IPV6_NODE
, &exit_address_family_cmd
);
4403 install_node(&bgp_ipv6m_node
);
4404 install_element(BGP_NODE
, &address_family_ipv6_multicast_cmd
);
4405 install_element(BGP_IPV6M_NODE
, &vtysh_exit_bgpd_cmd
);
4406 install_element(BGP_IPV6M_NODE
, &vtysh_quit_bgpd_cmd
);
4407 install_element(BGP_IPV6M_NODE
, &vtysh_end_all_cmd
);
4408 install_element(BGP_IPV6M_NODE
, &exit_address_family_cmd
);
4410 install_node(&bgp_ipv6l_node
);
4411 install_element(BGP_NODE
, &address_family_ipv6_labeled_unicast_cmd
);
4412 install_element(BGP_IPV6L_NODE
, &vtysh_exit_bgpd_cmd
);
4413 install_element(BGP_IPV6L_NODE
, &vtysh_quit_bgpd_cmd
);
4414 install_element(BGP_IPV6L_NODE
, &vtysh_end_all_cmd
);
4415 install_element(BGP_IPV6L_NODE
, &exit_address_family_cmd
);
4417 #if defined(ENABLE_BGP_VNC)
4418 install_node(&bgp_vrf_policy_node
);
4419 install_element(BGP_NODE
, &vnc_vrf_policy_cmd
);
4420 install_element(BGP_VRF_POLICY_NODE
, &vtysh_exit_bgpd_cmd
);
4421 install_element(BGP_VRF_POLICY_NODE
, &vtysh_quit_bgpd_cmd
);
4422 install_element(BGP_VRF_POLICY_NODE
, &vtysh_end_all_cmd
);
4423 install_element(BGP_VRF_POLICY_NODE
, &exit_vrf_policy_cmd
);
4425 install_node(&bgp_vnc_defaults_node
);
4426 install_element(BGP_NODE
, &vnc_defaults_cmd
);
4427 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_exit_bgpd_cmd
);
4428 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_quit_bgpd_cmd
);
4429 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_end_all_cmd
);
4430 install_element(BGP_VNC_DEFAULTS_NODE
, &exit_vnc_config_cmd
);
4432 install_node(&bgp_vnc_nve_group_node
);
4433 install_element(BGP_NODE
, &vnc_nve_group_cmd
);
4434 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4435 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4436 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_end_all_cmd
);
4437 install_element(BGP_VNC_NVE_GROUP_NODE
, &exit_vnc_config_cmd
);
4439 install_node(&bgp_vnc_l2_group_node
);
4440 install_element(BGP_NODE
, &vnc_l2_group_cmd
);
4441 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4442 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4443 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_end_all_cmd
);
4444 install_element(BGP_VNC_L2_GROUP_NODE
, &exit_vnc_config_cmd
);
4447 install_node(&bgp_evpn_node
);
4448 install_element(BGP_NODE
, &address_family_evpn_cmd
);
4449 install_element(BGP_EVPN_NODE
, &vtysh_quit_bgpd_cmd
);
4450 install_element(BGP_EVPN_NODE
, &vtysh_exit_bgpd_cmd
);
4451 install_element(BGP_EVPN_NODE
, &vtysh_end_all_cmd
);
4452 install_element(BGP_EVPN_NODE
, &exit_address_family_cmd
);
4454 install_node(&bgp_evpn_vni_node
);
4455 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
4456 install_element(BGP_EVPN_VNI_NODE
, &vtysh_exit_bgpd_cmd
);
4457 install_element(BGP_EVPN_VNI_NODE
, &vtysh_quit_bgpd_cmd
);
4458 install_element(BGP_EVPN_VNI_NODE
, &vtysh_end_all_cmd
);
4459 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
4461 install_node(&rpki_node
);
4462 install_element(CONFIG_NODE
, &rpki_cmd
);
4463 install_element(RPKI_NODE
, &rpki_exit_cmd
);
4464 install_element(RPKI_NODE
, &rpki_quit_cmd
);
4465 install_element(RPKI_NODE
, &vtysh_end_all_cmd
);
4467 install_node(&bmp_node
);
4468 install_element(BGP_NODE
, &bmp_targets_cmd
);
4469 install_element(BMP_NODE
, &bmp_exit_cmd
);
4470 install_element(BMP_NODE
, &bmp_quit_cmd
);
4471 install_element(BMP_NODE
, &vtysh_end_all_cmd
);
4473 install_node(&bgp_srv6_node
);
4474 install_element(BGP_NODE
, &bgp_srv6_cmd
);
4475 install_element(BGP_SRV6_NODE
, &exit_bgp_srv6_cmd
);
4476 install_element(BGP_SRV6_NODE
, &quit_bgp_srv6_cmd
);
4477 install_element(BGP_SRV6_NODE
, &vtysh_end_all_cmd
);
4478 #endif /* HAVE_BGPD */
4481 install_node(&rip_node
);
4483 install_element(CONFIG_NODE
, &router_rip_cmd
);
4484 install_element(RIP_NODE
, &vtysh_exit_ripd_cmd
);
4485 install_element(RIP_NODE
, &vtysh_quit_ripd_cmd
);
4486 install_element(RIP_NODE
, &vtysh_end_all_cmd
);
4487 #endif /* HAVE_RIPD */
4490 install_node(&ripng_node
);
4492 install_element(CONFIG_NODE
, &router_ripng_cmd
);
4493 install_element(RIPNG_NODE
, &vtysh_exit_ripngd_cmd
);
4494 install_element(RIPNG_NODE
, &vtysh_quit_ripngd_cmd
);
4495 install_element(RIPNG_NODE
, &vtysh_end_all_cmd
);
4496 #endif /* HAVE_RIPNGD */
4500 install_node(&ospf_node
);
4501 install_element(CONFIG_NODE
, &router_ospf_cmd
);
4502 install_element(OSPF_NODE
, &vtysh_exit_ospfd_cmd
);
4503 install_element(OSPF_NODE
, &vtysh_quit_ospfd_cmd
);
4504 install_element(OSPF_NODE
, &vtysh_end_all_cmd
);
4505 #endif /* HAVE_OSPFD */
4509 install_node(&ospf6_node
);
4510 install_element(CONFIG_NODE
, &router_ospf6_cmd
);
4511 install_element(OSPF6_NODE
, &vtysh_exit_ospf6d_cmd
);
4512 install_element(OSPF6_NODE
, &vtysh_quit_ospf6d_cmd
);
4513 install_element(OSPF6_NODE
, &vtysh_end_all_cmd
);
4514 #endif /* HAVE_OSPF6D */
4517 #if defined(HAVE_LDPD)
4518 install_node(&ldp_node
);
4519 install_element(CONFIG_NODE
, &ldp_mpls_ldp_cmd
);
4520 install_element(LDP_NODE
, &vtysh_exit_ldpd_cmd
);
4521 install_element(LDP_NODE
, &vtysh_quit_ldpd_cmd
);
4522 install_element(LDP_NODE
, &vtysh_end_all_cmd
);
4524 install_node(&ldp_ipv4_node
);
4525 install_element(LDP_NODE
, &ldp_address_family_ipv4_cmd
);
4526 install_element(LDP_IPV4_NODE
, &vtysh_exit_ldpd_cmd
);
4527 install_element(LDP_IPV4_NODE
, &vtysh_quit_ldpd_cmd
);
4528 install_element(LDP_IPV4_NODE
, &ldp_exit_address_family_cmd
);
4529 install_element(LDP_IPV4_NODE
, &vtysh_end_all_cmd
);
4531 install_node(&ldp_ipv6_node
);
4532 install_element(LDP_NODE
, &ldp_address_family_ipv6_cmd
);
4533 install_element(LDP_IPV6_NODE
, &vtysh_exit_ldpd_cmd
);
4534 install_element(LDP_IPV6_NODE
, &vtysh_quit_ldpd_cmd
);
4535 install_element(LDP_IPV6_NODE
, &ldp_exit_address_family_cmd
);
4536 install_element(LDP_IPV6_NODE
, &vtysh_end_all_cmd
);
4538 install_node(&ldp_ipv4_iface_node
);
4539 install_element(LDP_IPV4_NODE
, &ldp_interface_ifname_cmd
);
4540 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4541 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4542 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_end_all_cmd
);
4544 install_node(&ldp_ipv6_iface_node
);
4545 install_element(LDP_IPV6_NODE
, &ldp_interface_ifname_cmd
);
4546 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4547 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4548 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_end_all_cmd
);
4550 install_node(&ldp_l2vpn_node
);
4551 install_element(CONFIG_NODE
, &ldp_l2vpn_word_type_vpls_cmd
);
4552 install_element(LDP_L2VPN_NODE
, &vtysh_exit_ldpd_cmd
);
4553 install_element(LDP_L2VPN_NODE
, &vtysh_quit_ldpd_cmd
);
4554 install_element(LDP_L2VPN_NODE
, &vtysh_end_all_cmd
);
4556 install_node(&ldp_pseudowire_node
);
4557 install_element(LDP_L2VPN_NODE
, &ldp_member_pseudowire_ifname_cmd
);
4558 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_exit_ldpd_cmd
);
4559 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_quit_ldpd_cmd
);
4560 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_end_all_cmd
);
4565 install_node(&eigrp_node
);
4566 install_element(CONFIG_NODE
, &router_eigrp_cmd
);
4567 install_element(EIGRP_NODE
, &vtysh_exit_eigrpd_cmd
);
4568 install_element(EIGRP_NODE
, &vtysh_quit_eigrpd_cmd
);
4569 install_element(EIGRP_NODE
, &vtysh_end_all_cmd
);
4570 #endif /* HAVE_EIGRPD */
4574 install_node(&babel_node
);
4575 install_element(CONFIG_NODE
, &router_babel_cmd
);
4576 install_element(BABEL_NODE
, &vtysh_exit_babeld_cmd
);
4577 install_element(BABEL_NODE
, &vtysh_quit_babeld_cmd
);
4578 install_element(BABEL_NODE
, &vtysh_end_all_cmd
);
4579 #endif /* HAVE_BABELD */
4583 install_node(&isis_node
);
4584 install_element(CONFIG_NODE
, &router_isis_cmd
);
4585 install_element(ISIS_NODE
, &vtysh_exit_isisd_cmd
);
4586 install_element(ISIS_NODE
, &vtysh_quit_isisd_cmd
);
4587 install_element(ISIS_NODE
, &vtysh_end_all_cmd
);
4588 #endif /* HAVE_ISISD */
4592 install_node(&openfabric_node
);
4593 install_element(CONFIG_NODE
, &router_openfabric_cmd
);
4594 install_element(OPENFABRIC_NODE
, &vtysh_exit_fabricd_cmd
);
4595 install_element(OPENFABRIC_NODE
, &vtysh_quit_fabricd_cmd
);
4596 install_element(OPENFABRIC_NODE
, &vtysh_end_all_cmd
);
4597 #endif /* HAVE_FABRICD */
4601 install_node(&pbr_map_node
);
4602 install_element(CONFIG_NODE
, &vtysh_pbr_map_cmd
);
4603 install_element(CONFIG_NODE
, &vtysh_no_pbr_map_cmd
);
4604 install_element(PBRMAP_NODE
, &vtysh_exit_pbr_map_cmd
);
4605 install_element(PBRMAP_NODE
, &vtysh_quit_pbr_map_cmd
);
4606 install_element(PBRMAP_NODE
, &vtysh_end_all_cmd
);
4607 #endif /* HAVE_PBRD */
4611 install_node(&bfd_node
);
4612 install_element(CONFIG_NODE
, &bfd_enter_cmd
);
4613 install_element(BFD_NODE
, &vtysh_exit_bfdd_cmd
);
4614 install_element(BFD_NODE
, &vtysh_quit_bfdd_cmd
);
4615 install_element(BFD_NODE
, &vtysh_end_all_cmd
);
4617 install_node(&bfd_peer_node
);
4618 install_element(BFD_NODE
, &bfd_peer_enter_cmd
);
4619 install_element(BFD_PEER_NODE
, &vtysh_exit_bfdd_cmd
);
4620 install_element(BFD_PEER_NODE
, &vtysh_quit_bfdd_cmd
);
4621 install_element(BFD_PEER_NODE
, &vtysh_end_all_cmd
);
4623 install_node(&bfd_profile_node
);
4624 install_element(BFD_NODE
, &bfd_profile_enter_cmd
);
4625 install_element(BFD_PROFILE_NODE
, &vtysh_exit_bfdd_cmd
);
4626 install_element(BFD_PROFILE_NODE
, &vtysh_quit_bfdd_cmd
);
4627 install_element(BFD_PROFILE_NODE
, &vtysh_end_all_cmd
);
4628 #endif /* HAVE_BFDD */
4630 install_node(&segment_routing_node
);
4631 install_element(CONFIG_NODE
, &segment_routing_cmd
);
4632 install_element(SEGMENT_ROUTING_NODE
, &vtysh_exit_sr_cmd
);
4633 install_element(SEGMENT_ROUTING_NODE
, &vtysh_quit_sr_cmd
);
4634 install_element(SEGMENT_ROUTING_NODE
, &vtysh_end_all_cmd
);
4636 #if defined(HAVE_PATHD)
4637 install_node(&sr_traffic_eng_node
);
4638 install_node(&srte_segment_list_node
);
4639 install_node(&srte_policy_node
);
4640 install_node(&srte_candidate_dyn_node
);
4642 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_exit_pathd_cmd
);
4643 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_quit_pathd_cmd
);
4644 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_exit_pathd_cmd
);
4645 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_quit_pathd_cmd
);
4646 install_element(SR_POLICY_NODE
, &vtysh_exit_pathd_cmd
);
4647 install_element(SR_POLICY_NODE
, &vtysh_quit_pathd_cmd
);
4648 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_exit_pathd_cmd
);
4649 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_quit_pathd_cmd
);
4652 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_end_all_cmd
);
4653 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_end_all_cmd
);
4654 install_element(SR_POLICY_NODE
, &vtysh_end_all_cmd
);
4655 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_end_all_cmd
);
4657 install_element(SEGMENT_ROUTING_NODE
, &sr_traffic_eng_cmd
);
4658 install_element(SR_TRAFFIC_ENG_NODE
, &srte_segment_list_cmd
);
4659 install_element(SR_TRAFFIC_ENG_NODE
, &srte_policy_cmd
);
4660 install_element(SR_POLICY_NODE
, &srte_policy_candidate_dyn_path_cmd
);
4662 install_node(&pcep_node
);
4663 install_node(&pcep_pcc_node
);
4664 install_node(&pcep_pce_node
);
4665 install_node(&pcep_pce_config_node
);
4667 install_element(PCEP_NODE
, &vtysh_exit_pathd_cmd
);
4668 install_element(PCEP_NODE
, &vtysh_quit_pathd_cmd
);
4669 install_element(PCEP_PCC_NODE
, &vtysh_exit_pathd_cmd
);
4670 install_element(PCEP_PCC_NODE
, &vtysh_quit_pathd_cmd
);
4671 install_element(PCEP_PCE_NODE
, &vtysh_exit_pathd_cmd
);
4672 install_element(PCEP_PCE_NODE
, &vtysh_quit_pathd_cmd
);
4673 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_exit_pathd_cmd
);
4674 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_quit_pathd_cmd
);
4676 install_element(PCEP_NODE
, &vtysh_end_all_cmd
);
4677 install_element(PCEP_PCC_NODE
, &vtysh_end_all_cmd
);
4678 install_element(PCEP_PCE_NODE
, &vtysh_end_all_cmd
);
4679 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_end_all_cmd
);
4681 install_element(SR_TRAFFIC_ENG_NODE
, &pcep_cmd
);
4682 install_element(PCEP_NODE
, &pcep_cli_pcc_cmd
);
4683 install_element(PCEP_NODE
, &pcep_cli_pcep_pce_config_cmd
);
4684 install_element(PCEP_NODE
, &pcep_cli_pce_cmd
);
4686 #endif /* HAVE_PATHD */
4689 install_node(&keychain_node
);
4690 install_element(CONFIG_NODE
, &key_chain_cmd
);
4691 install_element(KEYCHAIN_NODE
, &key_chain_cmd
);
4692 install_element(KEYCHAIN_NODE
, &vtysh_exit_keys_cmd
);
4693 install_element(KEYCHAIN_NODE
, &vtysh_quit_keys_cmd
);
4694 install_element(KEYCHAIN_NODE
, &vtysh_end_all_cmd
);
4696 install_node(&keychain_key_node
);
4697 install_element(KEYCHAIN_NODE
, &key_cmd
);
4698 install_element(KEYCHAIN_KEY_NODE
, &key_chain_cmd
);
4699 install_element(KEYCHAIN_KEY_NODE
, &vtysh_exit_keys_cmd
);
4700 install_element(KEYCHAIN_KEY_NODE
, &vtysh_quit_keys_cmd
);
4701 install_element(KEYCHAIN_KEY_NODE
, &vtysh_end_all_cmd
);
4704 install_node(&nh_group_node
);
4705 install_element(CONFIG_NODE
, &vtysh_nexthop_group_cmd
);
4706 install_element(CONFIG_NODE
, &vtysh_no_nexthop_group_cmd
);
4707 install_element(NH_GROUP_NODE
, &vtysh_end_all_cmd
);
4708 install_element(NH_GROUP_NODE
, &vtysh_exit_nexthop_group_cmd
);
4709 install_element(NH_GROUP_NODE
, &vtysh_quit_nexthop_group_cmd
);
4712 install_node(&zebra_node
);
4714 install_node(&interface_node
);
4715 install_element(CONFIG_NODE
, &vtysh_interface_cmd
);
4716 install_element(INTERFACE_NODE
, &vtysh_end_all_cmd
);
4717 install_element(INTERFACE_NODE
, &vtysh_exit_interface_cmd
);
4718 install_element(INTERFACE_NODE
, &vtysh_quit_interface_cmd
);
4720 install_node(&link_params_node
);
4721 install_element(INTERFACE_NODE
, &vtysh_link_params_cmd
);
4722 install_element(LINK_PARAMS_NODE
, &exit_link_params_cmd
);
4723 install_element(LINK_PARAMS_NODE
, &vtysh_end_all_cmd
);
4724 install_element(LINK_PARAMS_NODE
, &vtysh_exit_link_params_cmd
);
4725 install_element(LINK_PARAMS_NODE
, &vtysh_quit_link_params_cmd
);
4727 install_node(&pw_node
);
4728 install_element(CONFIG_NODE
, &vtysh_pseudowire_cmd
);
4729 install_element(PW_NODE
, &vtysh_end_all_cmd
);
4730 install_element(PW_NODE
, &vtysh_exit_pseudowire_cmd
);
4731 install_element(PW_NODE
, &vtysh_quit_pseudowire_cmd
);
4733 install_node(&vrf_node
);
4734 install_element(CONFIG_NODE
, &vtysh_vrf_cmd
);
4735 install_element(VRF_NODE
, &exit_vrf_config_cmd
);
4736 install_element(VRF_NODE
, &vtysh_end_all_cmd
);
4737 install_element(VRF_NODE
, &vtysh_exit_vrf_cmd
);
4738 install_element(VRF_NODE
, &vtysh_quit_vrf_cmd
);
4740 install_node(&rmap_node
);
4741 install_element(CONFIG_NODE
, &vtysh_route_map_cmd
);
4742 install_element(RMAP_NODE
, &vtysh_exit_rmap_cmd
);
4743 install_element(RMAP_NODE
, &vtysh_quit_rmap_cmd
);
4744 install_element(RMAP_NODE
, &vtysh_end_all_cmd
);
4746 install_node(&vty_node
);
4747 install_element(CONFIG_NODE
, &vtysh_line_vty_cmd
);
4748 install_element(VTY_NODE
, &vtysh_exit_line_vty_cmd
);
4749 install_element(VTY_NODE
, &vtysh_quit_line_vty_cmd
);
4750 install_element(VTY_NODE
, &vtysh_end_all_cmd
);
4753 struct cmd_node
*node
;
4754 for (unsigned int i
= 0; i
< vector_active(cmdvec
); i
++) {
4755 node
= vector_slot(cmdvec
, i
);
4756 if (!node
|| node
->node
== VIEW_NODE
)
4758 vtysh_install_default(node
->node
);
4764 install_element(VIEW_NODE
, &vtysh_enable_cmd
);
4765 install_element(ENABLE_NODE
, &vtysh_config_terminal_cmd
);
4766 install_element(ENABLE_NODE
, &vtysh_disable_cmd
);
4768 /* "exit" command. */
4769 install_element(VIEW_NODE
, &vtysh_exit_all_cmd
);
4770 install_element(CONFIG_NODE
, &vtysh_exit_all_cmd
);
4771 install_element(VIEW_NODE
, &vtysh_quit_all_cmd
);
4772 install_element(CONFIG_NODE
, &vtysh_quit_all_cmd
);
4774 /* "end" command. */
4775 install_element(CONFIG_NODE
, &vtysh_end_all_cmd
);
4776 install_element(ENABLE_NODE
, &vtysh_end_all_cmd
);
4778 /* SRv6 Data-plane */
4779 install_node(&srv6_node
);
4780 install_element(SEGMENT_ROUTING_NODE
, &srv6_cmd
);
4781 install_element(SRV6_NODE
, &srv6_locators_cmd
);
4782 install_element(SRV6_NODE
, &exit_srv6_config_cmd
);
4783 install_element(SRV6_NODE
, &vtysh_end_all_cmd
);
4785 install_node(&srv6_locs_node
);
4786 install_element(SRV6_LOCS_NODE
, &srv6_locator_cmd
);
4787 install_element(SRV6_LOCS_NODE
, &exit_srv6_locs_config_cmd
);
4788 install_element(SRV6_LOCS_NODE
, &vtysh_end_all_cmd
);
4790 install_node(&srv6_loc_node
);
4791 install_element(SRV6_LOC_NODE
, &exit_srv6_loc_config_cmd
);
4792 install_element(SRV6_LOC_NODE
, &vtysh_end_all_cmd
);
4794 install_element(ENABLE_NODE
, &vtysh_show_running_config_cmd
);
4795 install_element(ENABLE_NODE
, &vtysh_copy_running_config_cmd
);
4796 install_element(ENABLE_NODE
, &vtysh_copy_to_running_cmd
);
4798 /* "write terminal" command. */
4799 install_element(ENABLE_NODE
, &vtysh_write_terminal_cmd
);
4801 install_element(CONFIG_NODE
, &vtysh_integrated_config_cmd
);
4802 install_element(CONFIG_NODE
, &no_vtysh_integrated_config_cmd
);
4804 /* "write memory" command. */
4805 install_element(ENABLE_NODE
, &vtysh_write_memory_cmd
);
4807 install_element(CONFIG_NODE
, &vtysh_terminal_paginate_cmd
);
4808 install_element(VIEW_NODE
, &vtysh_terminal_paginate_cmd
);
4809 install_element(VIEW_NODE
, &vtysh_terminal_length_cmd
);
4810 install_element(VIEW_NODE
, &vtysh_terminal_no_length_cmd
);
4811 install_element(VIEW_NODE
, &vtysh_show_daemons_cmd
);
4813 install_element(VIEW_NODE
, &vtysh_terminal_monitor_cmd
);
4814 install_element(VIEW_NODE
, &no_vtysh_terminal_monitor_cmd
);
4816 install_element(VIEW_NODE
, &vtysh_ping_cmd
);
4817 install_element(VIEW_NODE
, &vtysh_ping_ip_cmd
);
4818 install_element(VIEW_NODE
, &vtysh_traceroute_cmd
);
4819 install_element(VIEW_NODE
, &vtysh_traceroute_ip_cmd
);
4820 install_element(VIEW_NODE
, &vtysh_mtrace_cmd
);
4821 install_element(VIEW_NODE
, &vtysh_ping6_cmd
);
4822 install_element(VIEW_NODE
, &vtysh_traceroute6_cmd
);
4823 #if defined(HAVE_SHELL_ACCESS)
4824 install_element(VIEW_NODE
, &vtysh_telnet_cmd
);
4825 install_element(VIEW_NODE
, &vtysh_telnet_port_cmd
);
4826 install_element(VIEW_NODE
, &vtysh_ssh_cmd
);
4828 #if defined(HAVE_SHELL_ACCESS)
4829 install_element(ENABLE_NODE
, &vtysh_start_shell_cmd
);
4830 install_element(ENABLE_NODE
, &vtysh_start_bash_cmd
);
4831 install_element(ENABLE_NODE
, &vtysh_start_zsh_cmd
);
4835 install_element(VIEW_NODE
, &vtysh_show_error_code_cmd
);
4836 install_element(ENABLE_NODE
, &vtysh_show_debugging_cmd
);
4837 install_element(ENABLE_NODE
, &vtysh_show_debugging_hashtable_cmd
);
4838 install_element(ENABLE_NODE
, &vtysh_debug_all_cmd
);
4839 install_element(CONFIG_NODE
, &vtysh_debug_all_cmd
);
4840 install_element(ENABLE_NODE
, &vtysh_debug_memstats_cmd
);
4841 install_element(CONFIG_NODE
, &vtysh_debug_memstats_cmd
);
4842 install_element(ENABLE_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4843 install_element(CONFIG_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4846 install_element(ENABLE_NODE
, &show_config_running_cmd
);
4847 install_element(ENABLE_NODE
, &show_yang_operational_data_cmd
);
4848 install_element(ENABLE_NODE
, &show_yang_module_cmd
);
4849 install_element(ENABLE_NODE
, &show_yang_module_detail_cmd
);
4850 install_element(ENABLE_NODE
, &debug_nb_cmd
);
4851 install_element(CONFIG_NODE
, &debug_nb_cmd
);
4853 /* misc lib show commands */
4854 install_element(VIEW_NODE
, &vtysh_show_history_cmd
);
4855 install_element(VIEW_NODE
, &vtysh_show_memory_cmd
);
4856 install_element(VIEW_NODE
, &vtysh_show_modules_cmd
);
4857 install_element(VIEW_NODE
, &vtysh_show_work_queues_cmd
);
4858 install_element(VIEW_NODE
, &vtysh_show_work_queues_daemon_cmd
);
4859 install_element(VIEW_NODE
, &vtysh_show_thread_cmd
);
4860 install_element(VIEW_NODE
, &vtysh_show_poll_cmd
);
4863 install_element(VIEW_NODE
, &vtysh_show_logging_cmd
);
4865 install_element(CONFIG_NODE
, &vtysh_service_password_encrypt_cmd
);
4866 install_element(CONFIG_NODE
, &no_vtysh_service_password_encrypt_cmd
);
4868 install_element(CONFIG_NODE
, &vtysh_password_cmd
);
4869 install_element(CONFIG_NODE
, &no_vtysh_password_cmd
);
4870 install_element(CONFIG_NODE
, &vtysh_enable_password_cmd
);
4871 install_element(CONFIG_NODE
, &no_vtysh_enable_password_cmd
);