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
;
79 static bool stderr_tty
;
80 static bool stderr_stdout_same
;
82 /* Some utility functions for working on vtysh-specific vty tasks */
84 static FILE *vty_open_pager(struct vty
*vty
)
89 if (!vtysh_pager_name
)
92 vty
->of_saved
= vty
->of
;
93 vty
->of
= popen(vtysh_pager_name
, "w");
94 if (vty
->of
== NULL
) {
95 vty
->of
= vty
->of_saved
;
100 vty
->is_paged
= true;
105 static int vty_close_pager(struct vty
*vty
)
111 if (pclose(vty
->of
) == -1) {
116 vty
->of
= vty
->of_saved
;
117 vty
->is_paged
= false;
122 static void vtysh_pager_envdef(bool fallback
)
126 pager_defined
= getenv("VTYSH_PAGER");
129 vtysh_pager_name
= strdup(pager_defined
);
131 vtysh_pager_name
= strdup(VTYSH_PAGER
);
136 struct vtysh_client vtysh_client
[] = {
137 {.name
= "zebra", .flag
= VTYSH_ZEBRA
},
138 {.name
= "ripd", .flag
= VTYSH_RIPD
},
139 {.name
= "ripngd", .flag
= VTYSH_RIPNGD
},
140 {.name
= "ospfd", .flag
= VTYSH_OSPFD
},
141 {.name
= "ospf6d", .flag
= VTYSH_OSPF6D
},
142 {.name
= "ldpd", .flag
= VTYSH_LDPD
},
143 {.name
= "bgpd", .flag
= VTYSH_BGPD
},
144 {.name
= "isisd", .flag
= VTYSH_ISISD
},
145 {.name
= "pimd", .flag
= VTYSH_PIMD
},
146 {.name
= "nhrpd", .flag
= VTYSH_NHRPD
},
147 {.name
= "eigrpd", .flag
= VTYSH_EIGRPD
},
148 {.name
= "babeld", .flag
= VTYSH_BABELD
},
149 {.name
= "sharpd", .flag
= VTYSH_SHARPD
},
150 {.name
= "fabricd", .flag
= VTYSH_FABRICD
},
151 {.name
= "watchfrr", .flag
= VTYSH_WATCHFRR
},
152 {.name
= "pbrd", .flag
= VTYSH_PBRD
},
153 {.name
= "staticd", .flag
= VTYSH_STATICD
},
154 {.name
= "bfdd", .flag
= VTYSH_BFDD
},
155 {.name
= "vrrpd", .flag
= VTYSH_VRRPD
},
156 {.name
= "pathd", .flag
= VTYSH_PATHD
},
157 {.name
= "pim6d", .flag
= VTYSH_PIM6D
},
160 /* Searches for client by name, returns index */
161 static int vtysh_client_lookup(const char *name
)
165 for (unsigned int i
= 0; i
< array_size(vtysh_client
); i
++) {
166 if (strmatch(vtysh_client
[i
].name
, name
)) {
175 enum vtysh_write_integrated vtysh_write_integrated
=
176 WRITE_INTEGRATED_UNSPECIFIED
;
178 static int vtysh_reconnect(struct vtysh_client
*vclient
);
180 static void vclient_close(struct vtysh_client
*vclient
)
182 if (vclient
->fd
>= 0) {
185 "Warning: closing connection to %s because of an I/O error!\n",
188 /* indicate as candidate for reconnect */
189 vclient
->fd
= VTYSH_WAS_ACTIVE
;
193 static ssize_t
vtysh_client_receive(struct vtysh_client
*vclient
, char *buf
,
194 size_t bufsz
, int *pass_fd
)
196 struct iovec iov
[1] = {
203 uint8_t buf
[CMSG_SPACE(sizeof(int))];
204 struct cmsghdr align
;
208 .msg_iovlen
= array_size(iov
),
209 .msg_control
= u
.buf
,
210 .msg_controllen
= sizeof(u
.buf
),
212 struct cmsghdr
*cmh
= CMSG_FIRSTHDR(&mh
);
215 cmh
->cmsg_level
= SOL_SOCKET
;
216 cmh
->cmsg_type
= SCM_RIGHTS
;
217 cmh
->cmsg_len
= CMSG_LEN(sizeof(int));
218 memset(CMSG_DATA(cmh
), -1, sizeof(int));
221 ret
= recvmsg(vclient
->fd
, &mh
, 0);
222 if (ret
>= 0 || (errno
!= EINTR
&& errno
!= EAGAIN
))
226 if (cmh
->cmsg_len
== CMSG_LEN(sizeof(int))) {
229 memcpy(&fd
, CMSG_DATA(cmh
), sizeof(int));
241 * Send a CLI command to a client and read the response.
243 * Output will be printed to vty->of. If you want to suppress output, set that
247 * the client to send the command to
250 * the command to send
253 * if non-null, this will be called with each line of output received from
254 * the client passed in the second parameter
257 * optional first argument to pass to callback
262 static int vtysh_client_run(struct vtysh_client
*vclient
, const char *line
,
263 void (*callback
)(void *, const char *), void *cbarg
,
268 char *buf
= stackbuf
;
269 size_t bufsz
= sizeof(stackbuf
);
270 char *bufvalid
, *end
= NULL
;
271 char terminator
[3] = {0, 0, 0};
273 /* vclinet was previously active, try to reconnect */
274 if (vclient
->fd
== VTYSH_WAS_ACTIVE
) {
275 ret
= vtysh_reconnect(vclient
);
283 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
285 /* close connection and try to reconnect */
286 vclient_close(vclient
);
287 ret
= vtysh_reconnect(vclient
);
291 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
300 nread
= vtysh_client_receive(
301 vclient
, bufvalid
, buf
+ bufsz
- bufvalid
- 1, pass_fd
);
303 if (nread
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
309 "vtysh: error reading from %s: %s (%d)",
310 vclient
->name
, safe_strerror(errno
),
317 /* Null terminate so we may pass this to *printf later. */
321 * We expect string output from daemons, so instead of looking
322 * for the full 3 null bytes of the terminator, we check for
323 * just one instead and assume it is the first byte of the
324 * terminator. The presence of the full terminator is checked
327 if (bufvalid
- buf
>= 4)
328 end
= memmem(bufvalid
- 4, 4, "\0", 1);
331 * calculate # bytes we have, up to & not including the
332 * terminator if present
334 size_t textlen
= (end
? end
: bufvalid
) - buf
;
337 /* feed line processing callback if present */
338 while (callback
&& bufvalid
> buf
&& (end
> buf
|| !end
)) {
339 textlen
= (end
? end
: bufvalid
) - buf
;
340 char *eol
= memchr(buf
, '\n', textlen
);
346 * no line break, end of input, no text left
347 * before end; nothing to write
351 /* no nl, end of input, but some text left */
353 else if (bufvalid
== buf
+ bufsz
- 1) {
355 * no nl, no end of input, no buffer space;
361 if (buf
== stackbuf
) {
362 new = XMALLOC(MTYPE_TMP
, bufsz
);
363 memcpy(new, stackbuf
, sizeof(stackbuf
));
365 new = XREALLOC(MTYPE_TMP
, buf
, bufsz
);
367 bufvalid
= bufvalid
- buf
+ new;
369 /* if end != NULL, we won't be reading more
379 /* eol is at line end now, either \n => \0 or \0\0\0 */
380 assert(eol
&& eol
<= bufvalid
);
383 vty_out(vty
, "%s\n", buf
);
385 callback(cbarg
, buf
);
387 /* shift back data and adjust bufvalid */
388 memmove(buf
, eol
, bufvalid
- eol
);
389 bufvalid
-= eol
- buf
;
394 /* else if no callback, dump raw */
397 vty_out(vty
, "%s", buf
);
398 memmove(buf
, buf
+ textlen
, bufvalid
- buf
- textlen
);
404 * ----------------------------------------------------
405 * At this point `buf` should be in one of two states:
406 * - Empty (i.e. buf == bufvalid)
407 * - Contains up to 4 bytes of the terminator
408 * ----------------------------------------------------
410 assert(((buf
== bufvalid
)
411 || (bufvalid
- buf
<= 4 && buf
[0] == 0x00)));
414 /* if we have the terminator, break */
415 if (end
&& bufvalid
- buf
== 4) {
416 assert(!memcmp(buf
, terminator
, 3));
425 vclient_close(vclient
);
429 XFREE(MTYPE_TMP
, buf
);
433 static int vtysh_client_run_all(struct vtysh_client
*head_client
,
434 const char *line
, int continue_on_err
,
435 void (*callback
)(void *, const char *),
438 struct vtysh_client
*client
;
439 int rc
, rc_all
= CMD_SUCCESS
;
440 int correct_instance
= 0, wrong_instance
= 0;
442 for (client
= head_client
; client
; client
= client
->next
) {
443 rc
= vtysh_client_run(client
, line
, callback
, cbarg
, NULL
);
444 if (rc
== CMD_NOT_MY_INSTANCE
) {
450 if (rc
!= CMD_SUCCESS
) {
451 if (!continue_on_err
)
456 if (wrong_instance
&& !correct_instance
&& vty
->of
) {
458 "%% [%s]: command ignored as it targets an instance that is not running\n",
460 rc_all
= CMD_WARNING_CONFIG_FAILED
;
466 * Execute command against all daemons.
469 * where to start walking in the daemon list
472 * the specific command to execute
477 static int vtysh_client_execute(struct vtysh_client
*head_client
,
480 return vtysh_client_run_all(head_client
, line
, 0, NULL
, NULL
);
483 /* Execute by name */
484 static int vtysh_client_execute_name(const char *name
, const char *line
)
486 int ret
= CMD_SUCCESS
;
489 idx_client
= vtysh_client_lookup(name
);
490 if (idx_client
!= -1)
491 ret
= vtysh_client_execute(&vtysh_client
[idx_client
], line
);
493 vty_out(vty
, "Client not found\n");
501 * Retrieve all running config from daemons and parse it with the vtysh config
502 * parser. Returned output is not displayed to the user.
505 * where to start walking in the daemon list
508 * the specific command to execute
510 static void vtysh_client_config(struct vtysh_client
*head_client
, char *line
)
512 /* watchfrr currently doesn't load any config, and has some hardcoded
513 * settings that show up in "show run". skip it here (for now at
514 * least) so we don't get that mangled up in config-write.
516 if (head_client
->flag
== VTYSH_WATCHFRR
)
519 /* suppress output to user */
520 vty
->of_saved
= vty
->of
;
522 vtysh_client_run_all(head_client
, line
, 1, vtysh_config_parse_line
,
524 vty
->of
= vty
->of_saved
;
527 /* Command execution over the vty interface. */
528 static int vtysh_execute_func(const char *line
, int pager
)
533 const struct cmd_element
*cmd
;
535 int saved_ret
, saved_node
;
537 /* Split readline string up into the vector. */
538 vline
= cmd_make_strvec(line
);
543 if (vtysh_add_timestamp
&& strncmp(line
, "exit", 4)) {
546 (void)frr_timestamp(3, ts
, sizeof(ts
));
547 vty_out(vty
, "%% %s\n\n", ts
);
550 saved_ret
= ret
= cmd_execute(vty
, line
, &cmd
, 1);
551 saved_node
= vty
->node
;
554 * If command doesn't succeeded in current node, try to walk up in node
555 * tree. Changing vty->node is enough to try it just out without actual
556 * walkup in the vtysh.
558 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
559 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
560 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
561 && vty
->node
> CONFIG_NODE
) {
562 vty
->node
= node_parent(vty
->node
);
563 ret
= cmd_execute(vty
, line
, &cmd
, 1);
567 vty
->node
= saved_node
;
570 * If command succeeded in any other node than current (tried > 0) we
571 * have to move into node in the vtysh where it succeeded.
573 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
574 || ret
== CMD_WARNING
) {
576 vtysh_execute("exit");
579 * If command didn't succeed in any node, continue with return value
586 cmd_free_strvec(vline
);
591 case CMD_WARNING_CONFIG_FAILED
:
592 if (vty
->type
== VTY_FILE
)
593 vty_out(vty
, "Warning...\n");
595 case CMD_ERR_AMBIGUOUS
:
596 vty_out(vty
, "%% Ambiguous command: %s\n", line
);
598 case CMD_ERR_NO_MATCH
:
599 vty_out(vty
, "%% Unknown command: %s\n", line
);
601 case CMD_ERR_INCOMPLETE
:
602 vty_out(vty
, "%% Command incomplete: %s\n", line
);
604 case CMD_SUCCESS_DAEMON
: {
606 * FIXME: Don't open pager for exit commands. popen() causes
607 * problems if exited from vtysh at all. This hack shouldn't
608 * cause any problem but is really ugly.
610 if (pager
&& strncmp(line
, "exit", 4))
613 if (!strcmp(cmd
->string
, "configure")) {
614 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
615 cmd_stat
= vtysh_client_execute(
616 &vtysh_client
[i
], line
);
617 if (cmd_stat
== CMD_WARNING
)
623 vline
= cmd_make_strvec(line
);
628 vty_close_pager(vty
);
632 ret
= cmd_execute_command(vline
, vty
, &cmd
, 1);
633 cmd_free_strvec(vline
);
634 if (ret
!= CMD_SUCCESS_DAEMON
)
636 } else if (cmd
->func
) {
637 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
642 cmd_stat
= CMD_SUCCESS
;
643 struct vtysh_client
*vc
;
644 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
645 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
646 if (vtysh_client
[i
].fd
< 0
647 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
648 for (vc
= &vtysh_client
[i
]; vc
;
650 if (vc
->fd
== VTYSH_WAS_ACTIVE
)
653 if (vtysh_client
[i
].fd
< 0
654 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
655 bool any_inst
= false;
656 for (vc
= &vtysh_client
[i
]; vc
;
662 "%s is not running\n",
663 vtysh_client
[i
].name
);
664 cmd_stat
= CMD_ERR_NO_DAEMON
;
668 cmd_stat
= vtysh_client_execute(
669 &vtysh_client
[i
], line
);
670 if (cmd_stat
!= CMD_SUCCESS
)
674 if (cmd_stat
!= CMD_SUCCESS
&& cmd_stat
!= CMD_ERR_NO_DAEMON
)
678 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
682 vty_close_pager(vty
);
687 int vtysh_execute_no_pager(const char *line
)
689 return vtysh_execute_func(line
, 0);
692 int vtysh_execute(const char *line
)
694 return vtysh_execute_func(line
, 1);
697 static char *trim(char *s
)
708 while (end
>= s
&& isspace((unsigned char)*end
))
712 while (*s
&& isspace((unsigned char)*s
))
718 int vtysh_mark_file(const char *filename
)
725 const struct cmd_element
*cmd
;
726 int saved_ret
, prev_node
;
728 char *vty_buf_copy
= NULL
;
729 char *vty_buf_trimmed
= NULL
;
731 if (strncmp("-", filename
, 1) == 0)
734 confp
= fopen(filename
, "r");
737 fprintf(stderr
, "%% Can't open config file %s due to '%s'.\n",
738 filename
, safe_strerror(errno
));
739 return CMD_ERR_NO_FILE
;
743 vty
->wfd
= STDOUT_FILENO
;
744 vty
->type
= VTY_TERM
;
745 vty
->node
= CONFIG_NODE
;
747 vtysh_execute_no_pager("enable");
748 vtysh_execute_no_pager("configure");
749 vty_buf_copy
= XCALLOC(MTYPE_VTYSH_CMD
, VTY_BUFSIZ
);
751 while (fgets(vty
->buf
, VTY_BUFSIZ
, confp
)) {
754 strlcpy(vty_buf_copy
, vty
->buf
, VTY_BUFSIZ
);
755 vty_buf_trimmed
= trim(vty_buf_copy
);
757 if (vty_buf_trimmed
[0] == '!' || vty_buf_trimmed
[0] == '#') {
758 vty_out(vty
, "%s", vty
->buf
);
762 /* Split readline string up into the vector. */
763 vline
= cmd_make_strvec(vty
->buf
);
766 vty_out(vty
, "%s", vty
->buf
);
771 * Ignore the "end" lines, we will generate these where
774 if (strlen(vty_buf_trimmed
) == 3
775 && strncmp("end", vty_buf_trimmed
, 3) == 0) {
776 cmd_free_strvec(vline
);
780 prev_node
= vty
->node
;
781 saved_ret
= ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
784 * If command doesn't succeeded in current node, try to walk up
785 * in node tree. Changing vty->node is enough to try it just
786 * out without actual walkup in the vtysh.
788 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
789 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
790 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
791 && vty
->node
> CONFIG_NODE
) {
792 vty
->node
= node_parent(vty
->node
);
793 ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
798 * If command succeeded in any other node than current (tried >
799 * 0) we have to move into node in the vtysh where it
802 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
803 || ret
== CMD_WARNING
) {
805 vty_out(vty
, "exit\n");
808 * If command didn't succeed in any node, continue with return
809 * value from first try.
813 vty
->node
= prev_node
;
816 cmd_free_strvec(vline
);
819 case CMD_WARNING_CONFIG_FAILED
:
820 if (vty
->type
== VTY_FILE
)
821 fprintf(stderr
, "line %d: Warning...: %s\n",
825 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
827 case CMD_ERR_AMBIGUOUS
:
828 fprintf(stderr
, "line %d: %% Ambiguous command: %s\n",
832 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
833 return CMD_ERR_AMBIGUOUS
;
834 case CMD_ERR_NO_MATCH
:
835 fprintf(stderr
, "line %d: %% Unknown command: %s\n",
839 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
840 return CMD_ERR_NO_MATCH
;
841 case CMD_ERR_INCOMPLETE
:
842 fprintf(stderr
, "line %d: %% Command incomplete: %s\n",
846 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
847 return CMD_ERR_INCOMPLETE
;
849 vty_out(vty
, "%s", vty
->buf
);
850 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
851 vty_out(vty
, "end\n");
853 case CMD_SUCCESS_DAEMON
: {
856 vty_out(vty
, "%s", vty
->buf
);
857 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
858 vty_out(vty
, "end\n");
859 cmd_stat
= vtysh_client_execute(&vtysh_client
[0],
861 if (cmd_stat
!= CMD_SUCCESS
)
865 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
869 /* This is the end */
870 vty_out(vty
, "\nend\n");
872 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
880 /* Configuration make from file. */
881 int vtysh_config_from_file(struct vty
*vty
, FILE *fp
)
884 const struct cmd_element
*cmd
;
886 /* once we have an error, we remember & return that */
887 int retcode
= CMD_SUCCESS
;
889 while (fgets(vty
->buf
, VTY_BUFSIZ
, fp
)) {
892 ret
= command_config_read_one_line(vty
, &cmd
, lineno
, 1);
896 case CMD_WARNING_CONFIG_FAILED
:
897 if (vty
->type
== VTY_FILE
)
898 fprintf(stderr
, "line %d: Warning[%d]...: %s\n",
899 lineno
, vty
->node
, vty
->buf
);
903 case CMD_ERR_AMBIGUOUS
:
905 "line %d: %% Ambiguous command[%d]: %s\n",
906 lineno
, vty
->node
, vty
->buf
);
907 retcode
= CMD_ERR_AMBIGUOUS
;
909 case CMD_ERR_NO_MATCH
:
910 fprintf(stderr
, "line %d: %% Unknown command[%d]: %s",
911 lineno
, vty
->node
, vty
->buf
);
912 retcode
= CMD_ERR_NO_MATCH
;
914 case CMD_ERR_INCOMPLETE
:
916 "line %d: %% Command incomplete[%d]: %s\n",
917 lineno
, vty
->node
, vty
->buf
);
918 retcode
= CMD_ERR_INCOMPLETE
;
920 case CMD_SUCCESS_DAEMON
: {
922 int cmd_stat
= CMD_SUCCESS
;
924 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
925 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
926 cmd_stat
= vtysh_client_execute(
927 &vtysh_client
[i
], vty
->buf
);
929 * CMD_WARNING - Can mean that the
930 * command was parsed successfully but
931 * it was already entered in a few
932 * spots. As such if we receive a
933 * CMD_WARNING from a daemon we
934 * shouldn't stop talking to the other
935 * daemons for the particular command.
937 if (cmd_stat
!= CMD_SUCCESS
938 && cmd_stat
!= CMD_WARNING
) {
940 "line %d: Failure to communicate[%d] to %s, line: %s\n",
942 vtysh_client
[i
].name
,
949 if (cmd_stat
!= CMD_SUCCESS
)
953 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
962 * Function processes cli commands terminated with '?' character when entered
963 * through either 'vtysh' or 'vtysh -c' interfaces.
965 static int vtysh_process_questionmark(const char *input
, int input_len
)
969 vector vline
, describe
;
970 struct cmd_token
*token
;
975 vline
= cmd_make_strvec(input
);
977 /* In case of '> ?'. */
979 vline
= vector_init(1);
980 vector_set(vline
, NULL
);
981 } else if (input_len
&& isspace((unsigned char)input
[input_len
- 1]))
982 vector_set(vline
, NULL
);
984 describe
= cmd_describe_command(vline
, vty
, &ret
);
986 /* Ambiguous and no match error. */
988 case CMD_ERR_AMBIGUOUS
:
989 cmd_free_strvec(vline
);
990 vector_free(describe
);
991 vty_out(vty
, "%% Ambiguous command.\n");
994 case CMD_ERR_NO_MATCH
:
995 cmd_free_strvec(vline
);
997 vector_free(describe
);
998 vty_out(vty
, "%% There is no matched command.\n");
1003 /* Get width of command string. */
1005 for (i
= 0; i
< vector_active(describe
); i
++)
1006 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1007 if (token
->text
[0] == '\0')
1010 int len
= strlen(token
->text
);
1016 for (i
= 0; i
< vector_active(describe
); i
++)
1017 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1019 vty_out(vty
, " %-s\n", token
->text
);
1021 vty_out(vty
, " %-*s %s\n", width
, token
->text
,
1024 if (IS_VARYING_TOKEN(token
->type
)) {
1025 const char *ref
= vector_slot(
1026 vline
, vector_active(vline
) - 1);
1028 vector varcomps
= vector_init(VECTOR_MIN_SIZE
);
1029 cmd_variable_complete(token
, ref
, varcomps
);
1031 if (vector_active(varcomps
) > 0) {
1033 rl_get_screen_size(&rows
, &cols
);
1035 char *ac
= cmd_variable_comp2str(
1037 vty_out(vty
, "%s\n", ac
);
1038 XFREE(MTYPE_TMP
, ac
);
1041 vector_free(varcomps
);
1045 cmd_free_strvec(vline
);
1046 vector_free(describe
);
1052 * Entry point for user commands terminated with '?' character and typed through
1053 * the usual vtysh's stdin interface. This is the function being registered with
1056 static int vtysh_rl_describe(int a
, int b
)
1062 ret
= vtysh_process_questionmark(rl_line_buffer
, rl_end
);
1069 * Function in charged of processing vtysh instructions terminating with '?'
1070 * character and received through the 'vtysh -c' interface. If user's
1071 * instruction is well-formatted, we will call the same processing routine
1072 * utilized by the traditional vtysh's stdin interface.
1074 int vtysh_execute_command_questionmark(char *input
)
1076 int input_len
, qmark_count
= 0;
1079 if (!(input
&& *input
))
1082 /* Finding out question_mark count and strlen */
1083 for (str
= input
; *str
; ++str
) {
1087 input_len
= str
- input
;
1090 * Verify that user's input terminates in '?' and that patterns such as
1091 * 'cmd ? subcmd ?' are prevented.
1093 if (qmark_count
!= 1 || input
[input_len
- 1] != '?')
1097 * Questionmark-processing function is not expecting to receive '?'
1098 * character in input string.
1100 input
[input_len
- 1] = '\0';
1102 return vtysh_process_questionmark(input
, input_len
- 1);
1105 /* Result of cmd_complete_command() call will be stored here
1106 * and used in new_completion() in order to put the space in
1107 * correct places only. */
1108 int complete_status
;
1110 static char *command_generator(const char *text
, int state
)
1113 static char **matched
= NULL
;
1114 static int index
= 0;
1120 if (vty
->node
== AUTH_NODE
|| vty
->node
== AUTH_ENABLE_NODE
)
1123 vline
= cmd_make_strvec(rl_line_buffer
);
1128 isspace((unsigned char)rl_line_buffer
[rl_end
- 1]))
1129 vector_set(vline
, NULL
);
1131 matched
= cmd_complete_command(vline
, vty
, &complete_status
);
1132 cmd_free_strvec(vline
);
1135 if (matched
&& matched
[index
]) {
1136 XCOUNTFREE(MTYPE_COMPLETION
, matched
[index
]);
1137 return matched
[index
++];
1140 XFREE(MTYPE_TMP
, matched
);
1145 static char **new_completion(const char *text
, int start
, int end
)
1149 matches
= rl_completion_matches(text
, command_generator
);
1153 if (complete_status
!= CMD_COMPLETE_FULL_MATCH
)
1154 /* only append a space on full match */
1155 rl_completion_append_character
= '\0';
1161 /* Vty node structures. */
1163 static struct cmd_node bgp_node
= {
1166 .parent_node
= CONFIG_NODE
,
1167 .prompt
= "%s(config-router)# ",
1169 #endif /* HAVE_BGPD */
1171 static struct cmd_node rip_node
= {
1174 .parent_node
= CONFIG_NODE
,
1175 .prompt
= "%s(config-router)# ",
1179 static struct cmd_node isis_node
= {
1182 .parent_node
= CONFIG_NODE
,
1183 .prompt
= "%s(config-router)# ",
1185 #endif /* HAVE_ISISD */
1188 static struct cmd_node openfabric_node
= {
1189 .name
= "openfabric",
1190 .node
= OPENFABRIC_NODE
,
1191 .parent_node
= CONFIG_NODE
,
1192 .prompt
= "%s(config-router)# ",
1194 #endif /* HAVE_FABRICD */
1196 static struct cmd_node interface_node
= {
1197 .name
= "interface",
1198 .node
= INTERFACE_NODE
,
1199 .parent_node
= CONFIG_NODE
,
1200 .prompt
= "%s(config-if)# ",
1203 static struct cmd_node pw_node
= {
1206 .parent_node
= CONFIG_NODE
,
1207 .prompt
= "%s(config-pw)# ",
1210 static struct cmd_node segment_routing_node
= {
1211 .name
= "segment-routing",
1212 .node
= SEGMENT_ROUTING_NODE
,
1213 .parent_node
= CONFIG_NODE
,
1214 .prompt
= "%s(config-sr)# ",
1217 #if defined(HAVE_PATHD)
1218 static struct cmd_node sr_traffic_eng_node
= {
1219 .name
= "sr traffic-eng",
1220 .node
= SR_TRAFFIC_ENG_NODE
,
1221 .parent_node
= SEGMENT_ROUTING_NODE
,
1222 .prompt
= "%s(config-sr-te)# ",
1225 static struct cmd_node srte_segment_list_node
= {
1226 .name
= "srte segment-list",
1227 .node
= SR_SEGMENT_LIST_NODE
,
1228 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1229 .prompt
= "%s(config-sr-te-segment-list)# ",
1232 static struct cmd_node srte_policy_node
= {
1233 .name
= "srte policy",
1234 .node
= SR_POLICY_NODE
,
1235 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1236 .prompt
= "%s(config-sr-te-policy)# ",
1239 static struct cmd_node srte_candidate_dyn_node
= {
1240 .name
= "srte candidate-dyn",
1241 .node
= SR_CANDIDATE_DYN_NODE
,
1242 .parent_node
= SR_POLICY_NODE
,
1243 .prompt
= "%s(config-sr-te-candidate)# ",
1246 static struct cmd_node pcep_node
= {
1247 .name
= "srte pcep",
1249 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1250 .prompt
= "%s(config-sr-te-pcep)# "
1253 static struct cmd_node pcep_pcc_node
= {
1254 .name
= "srte pcep pcc",
1255 .node
= PCEP_PCC_NODE
,
1256 .parent_node
= PCEP_NODE
,
1257 .prompt
= "%s(config-sr-te-pcep-pcc)# ",
1260 static struct cmd_node pcep_pce_node
= {
1261 .name
= "srte pcep pce-peer",
1262 .node
= PCEP_PCE_NODE
,
1263 .parent_node
= PCEP_NODE
,
1264 .prompt
= "%s(config-sr-te-pcep-pce-peer)# ",
1267 static struct cmd_node pcep_pce_config_node
= {
1268 .name
= "srte pcep pce-config",
1269 .node
= PCEP_PCE_CONFIG_NODE
,
1270 .parent_node
= PCEP_NODE
,
1271 .prompt
= "%s(pcep-sr-te-pcep-pce-config)# ",
1273 #endif /* HAVE_PATHD */
1275 static struct cmd_node vrf_node
= {
1278 .parent_node
= CONFIG_NODE
,
1279 .prompt
= "%s(config-vrf)# ",
1282 static struct cmd_node nh_group_node
= {
1283 .name
= "nexthop-group",
1284 .node
= NH_GROUP_NODE
,
1285 .parent_node
= CONFIG_NODE
,
1286 .prompt
= "%s(config-nh-group)# ",
1289 static struct cmd_node rmap_node
= {
1292 .parent_node
= CONFIG_NODE
,
1293 .prompt
= "%s(config-route-map)# ",
1296 static struct cmd_node srv6_node
= {
1299 .parent_node
= SEGMENT_ROUTING_NODE
,
1300 .prompt
= "%s(config-srv6)# ",
1303 static struct cmd_node srv6_locs_node
= {
1304 .name
= "srv6-locators",
1305 .node
= SRV6_LOCS_NODE
,
1306 .parent_node
= SRV6_NODE
,
1307 .prompt
= "%s(config-srv6-locators)# ",
1310 static struct cmd_node srv6_loc_node
= {
1311 .name
= "srv6-locator",
1312 .node
= SRV6_LOC_NODE
,
1313 .parent_node
= SRV6_LOCS_NODE
,
1314 .prompt
= "%s(config-srv6-locator)# ",
1318 static struct cmd_node pbr_map_node
= {
1320 .node
= PBRMAP_NODE
,
1321 .parent_node
= CONFIG_NODE
,
1322 .prompt
= "%s(config-pbr-map)# ",
1324 #endif /* HAVE_PBRD */
1326 static struct cmd_node zebra_node
= {
1329 .parent_node
= CONFIG_NODE
,
1330 .prompt
= "%s(config-router)# ",
1334 static struct cmd_node bgp_vpnv4_node
= {
1335 .name
= "bgp vpnv4",
1336 .node
= BGP_VPNV4_NODE
,
1337 .parent_node
= BGP_NODE
,
1338 .prompt
= "%s(config-router-af)# ",
1342 static struct cmd_node bgp_vpnv6_node
= {
1343 .name
= "bgp vpnv6",
1344 .node
= BGP_VPNV6_NODE
,
1345 .parent_node
= BGP_NODE
,
1346 .prompt
= "%s(config-router-af)# ",
1350 static struct cmd_node bgp_flowspecv4_node
= {
1351 .name
= "bgp ipv4 flowspec",
1352 .node
= BGP_FLOWSPECV4_NODE
,
1353 .parent_node
= BGP_NODE
,
1354 .prompt
= "%s(config-router-af)# ",
1358 static struct cmd_node bgp_flowspecv6_node
= {
1359 .name
= "bgp ipv6 flowspec",
1360 .node
= BGP_FLOWSPECV6_NODE
,
1361 .parent_node
= BGP_NODE
,
1362 .prompt
= "%s(config-router-af)# ",
1366 static struct cmd_node bgp_ipv4_node
= {
1367 .name
= "bgp ipv4 unicast",
1368 .node
= BGP_IPV4_NODE
,
1369 .parent_node
= BGP_NODE
,
1370 .prompt
= "%s(config-router-af)# ",
1374 static struct cmd_node bgp_ipv4m_node
= {
1375 .name
= "bgp ipv4 multicast",
1376 .node
= BGP_IPV4M_NODE
,
1377 .parent_node
= BGP_NODE
,
1378 .prompt
= "%s(config-router-af)# ",
1382 static struct cmd_node bgp_ipv4l_node
= {
1383 .name
= "bgp ipv4 labeled unicast",
1384 .node
= BGP_IPV4L_NODE
,
1385 .parent_node
= BGP_NODE
,
1386 .prompt
= "%s(config-router-af)# ",
1390 static struct cmd_node bgp_ipv6_node
= {
1392 .node
= BGP_IPV6_NODE
,
1393 .parent_node
= BGP_NODE
,
1394 .prompt
= "%s(config-router-af)# ",
1398 static struct cmd_node bgp_ipv6m_node
= {
1399 .name
= "bgp ipv6 multicast",
1400 .node
= BGP_IPV6M_NODE
,
1401 .parent_node
= BGP_NODE
,
1402 .prompt
= "%s(config-router-af)# ",
1406 static struct cmd_node bgp_evpn_node
= {
1408 .node
= BGP_EVPN_NODE
,
1409 .parent_node
= BGP_NODE
,
1410 .prompt
= "%s(config-router-af)# ",
1414 static struct cmd_node bgp_evpn_vni_node
= {
1415 .name
= "bgp evpn vni",
1416 .node
= BGP_EVPN_VNI_NODE
,
1417 .parent_node
= BGP_EVPN_NODE
,
1418 .prompt
= "%s(config-router-af-vni)# ",
1421 static struct cmd_node bgp_ipv6l_node
= {
1422 .name
= "bgp ipv6 labeled unicast",
1423 .node
= BGP_IPV6L_NODE
,
1424 .parent_node
= BGP_NODE
,
1425 .prompt
= "%s(config-router-af)# ",
1429 #ifdef ENABLE_BGP_VNC
1430 static struct cmd_node bgp_vnc_defaults_node
= {
1431 .name
= "bgp vnc defaults",
1432 .node
= BGP_VNC_DEFAULTS_NODE
,
1433 .parent_node
= BGP_NODE
,
1434 .prompt
= "%s(config-router-vnc-defaults)# ",
1437 static struct cmd_node bgp_vnc_nve_group_node
= {
1438 .name
= "bgp vnc nve",
1439 .node
= BGP_VNC_NVE_GROUP_NODE
,
1440 .parent_node
= BGP_NODE
,
1441 .prompt
= "%s(config-router-vnc-nve-group)# ",
1444 static struct cmd_node bgp_vrf_policy_node
= {
1445 .name
= "bgp vrf policy",
1446 .node
= BGP_VRF_POLICY_NODE
,
1447 .parent_node
= BGP_NODE
,
1448 .prompt
= "%s(config-router-vrf-policy)# ",
1451 static struct cmd_node bgp_vnc_l2_group_node
= {
1452 .name
= "bgp vnc l2",
1453 .node
= BGP_VNC_L2_GROUP_NODE
,
1454 .parent_node
= BGP_NODE
,
1455 .prompt
= "%s(config-router-vnc-l2-group)# ",
1457 #endif /* ENABLE_BGP_VNC */
1459 static struct cmd_node bmp_node
= {
1462 .parent_node
= BGP_NODE
,
1463 .prompt
= "%s(config-bgp-bmp)# "
1466 static struct cmd_node bgp_srv6_node
= {
1468 .node
= BGP_SRV6_NODE
,
1469 .parent_node
= BGP_NODE
,
1470 .prompt
= "%s(config-router-srv6)# ",
1472 #endif /* HAVE_BGPD */
1475 static struct cmd_node ospf_node
= {
1478 .parent_node
= CONFIG_NODE
,
1479 .prompt
= "%s(config-router)# ",
1481 #endif /* HAVE_OSPFD */
1484 static struct cmd_node eigrp_node
= {
1487 .parent_node
= CONFIG_NODE
,
1488 .prompt
= "%s(config-router)# ",
1490 #endif /* HAVE_EIGRPD */
1493 static struct cmd_node babel_node
= {
1496 .parent_node
= CONFIG_NODE
,
1497 .prompt
= "%s(config-router)# ",
1499 #endif /* HAVE_BABELD */
1501 static struct cmd_node ripng_node
= {
1504 .parent_node
= CONFIG_NODE
,
1505 .prompt
= "%s(config-router)# ",
1509 static struct cmd_node ospf6_node
= {
1512 .parent_node
= CONFIG_NODE
,
1513 .prompt
= "%s(config-ospf6)# ",
1515 #endif /* HAVE_OSPF6D */
1518 static struct cmd_node ldp_node
= {
1521 .parent_node
= CONFIG_NODE
,
1522 .prompt
= "%s(config-ldp)# ",
1525 static struct cmd_node ldp_ipv4_node
= {
1527 .node
= LDP_IPV4_NODE
,
1528 .parent_node
= LDP_NODE
,
1529 .prompt
= "%s(config-ldp-af)# ",
1532 static struct cmd_node ldp_ipv6_node
= {
1534 .node
= LDP_IPV6_NODE
,
1535 .parent_node
= LDP_NODE
,
1536 .prompt
= "%s(config-ldp-af)# ",
1539 static struct cmd_node ldp_ipv4_iface_node
= {
1540 .name
= "ldp ipv4 interface",
1541 .node
= LDP_IPV4_IFACE_NODE
,
1542 .parent_node
= LDP_IPV4_NODE
,
1543 .prompt
= "%s(config-ldp-af-if)# ",
1546 static struct cmd_node ldp_ipv6_iface_node
= {
1547 .name
= "ldp ipv6 interface",
1548 .node
= LDP_IPV6_IFACE_NODE
,
1549 .parent_node
= LDP_IPV6_NODE
,
1550 .prompt
= "%s(config-ldp-af-if)# ",
1553 static struct cmd_node ldp_l2vpn_node
= {
1554 .name
= "ldp l2vpn",
1555 .node
= LDP_L2VPN_NODE
,
1556 .parent_node
= CONFIG_NODE
,
1557 .prompt
= "%s(config-l2vpn)# ",
1560 static struct cmd_node ldp_pseudowire_node
= {
1562 .node
= LDP_PSEUDOWIRE_NODE
,
1563 .parent_node
= LDP_L2VPN_NODE
,
1564 .prompt
= "%s(config-l2vpn-pw)# ",
1566 #endif /* HAVE_LDPD */
1568 static struct cmd_node keychain_node
= {
1570 .node
= KEYCHAIN_NODE
,
1571 .parent_node
= CONFIG_NODE
,
1572 .prompt
= "%s(config-keychain)# ",
1575 static struct cmd_node keychain_key_node
= {
1576 .name
= "keychain key",
1577 .node
= KEYCHAIN_KEY_NODE
,
1578 .parent_node
= KEYCHAIN_NODE
,
1579 .prompt
= "%s(config-keychain-key)# ",
1582 struct cmd_node link_params_node
= {
1583 .name
= "link-params",
1584 .node
= LINK_PARAMS_NODE
,
1585 .parent_node
= INTERFACE_NODE
,
1586 .prompt
= "%s(config-link-params)# ",
1591 static struct cmd_node rpki_node
= {
1594 .parent_node
= CONFIG_NODE
,
1595 .prompt
= "%s(config-rpki)# ",
1597 #endif /* HAVE_BGPD */
1600 static struct cmd_node bfd_node
= {
1603 .parent_node
= CONFIG_NODE
,
1604 .prompt
= "%s(config-bfd)# ",
1607 static struct cmd_node bfd_peer_node
= {
1609 .node
= BFD_PEER_NODE
,
1610 .parent_node
= BFD_NODE
,
1611 .prompt
= "%s(config-bfd-peer)# ",
1614 static struct cmd_node bfd_profile_node
= {
1615 .name
= "bfd profile",
1616 .node
= BFD_PROFILE_NODE
,
1617 .parent_node
= BFD_NODE
,
1618 .prompt
= "%s(config-bfd-profile)# ",
1620 #endif /* HAVE_BFDD */
1622 /* Defined in lib/vty.c */
1623 extern struct cmd_node vty_node
;
1625 /* When '^Z' is received from vty, move down to the enable mode. */
1626 static int vtysh_end(void)
1628 switch (vty
->node
) {
1631 /* Nothing to do. */
1634 vty
->node
= ENABLE_NODE
;
1640 #include "vtysh/vtysh_clippy.c"
1642 DEFUNSH(VTYSH_REALLYALL
, vtysh_end_all
, vtysh_end_all_cmd
, "end",
1643 "End current mode and change to enable mode\n")
1648 DEFUNSH(VTYSH_ZEBRA
, srv6
, srv6_cmd
,
1650 "Segment-Routing SRv6 configuration\n")
1652 vty
->node
= SRV6_NODE
;
1656 DEFUNSH(VTYSH_ZEBRA
, srv6_locators
, srv6_locators_cmd
,
1658 "Segment-Routing SRv6 locators configuration\n")
1660 vty
->node
= SRV6_LOCS_NODE
;
1664 DEFUNSH(VTYSH_ZEBRA
, srv6_locator
, srv6_locator_cmd
,
1666 "Segment Routing SRv6 locator\n"
1667 "Specify locator-name\n")
1669 vty
->node
= SRV6_LOC_NODE
;
1674 DEFUNSH(VTYSH_BGPD
, router_bgp
, router_bgp_cmd
,
1675 "router bgp [(1-4294967295) [<view|vrf> VIEWVRFNAME]]",
1676 ROUTER_STR BGP_STR AS_STR
1677 "BGP view\nBGP VRF\n"
1680 vty
->node
= BGP_NODE
;
1684 #ifdef KEEP_OLD_VPN_COMMANDS
1685 DEFUNSH(VTYSH_BGPD
, address_family_vpnv4
, address_family_vpnv4_cmd
,
1686 "address-family vpnv4 [unicast]",
1687 "Enter Address Family command mode\n"
1689 "Address Family modifier\n")
1691 vty
->node
= BGP_VPNV4_NODE
;
1695 DEFUNSH(VTYSH_BGPD
, address_family_vpnv6
, address_family_vpnv6_cmd
,
1696 "address-family vpnv6 [unicast]",
1697 "Enter Address Family command mode\n"
1699 "Address Family modifier\n")
1701 vty
->node
= BGP_VPNV6_NODE
;
1704 #endif /* KEEP_OLD_VPN_COMMANDS */
1706 DEFUNSH(VTYSH_BGPD
, address_family_ipv4
, address_family_ipv4_cmd
,
1707 "address-family ipv4 [unicast]",
1708 "Enter Address Family command mode\n"
1710 "Address Family Modifier\n")
1712 vty
->node
= BGP_IPV4_NODE
;
1716 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv4
, address_family_flowspecv4_cmd
,
1717 "address-family ipv4 flowspec",
1718 "Enter Address Family command mode\n"
1720 "Address Family Modifier\n")
1722 vty
->node
= BGP_FLOWSPECV4_NODE
;
1726 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv6
, address_family_flowspecv6_cmd
,
1727 "address-family ipv6 flowspec",
1728 "Enter Address Family command mode\n"
1730 "Address Family Modifier\n")
1732 vty
->node
= BGP_FLOWSPECV6_NODE
;
1736 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_multicast
,
1737 address_family_ipv4_multicast_cmd
, "address-family ipv4 multicast",
1738 "Enter Address Family command mode\n"
1740 "Address Family modifier\n")
1742 vty
->node
= BGP_IPV4M_NODE
;
1746 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_vpn
, address_family_ipv4_vpn_cmd
,
1747 "address-family ipv4 vpn",
1748 "Enter Address Family command mode\n"
1750 "Address Family modifier\n")
1752 vty
->node
= BGP_VPNV4_NODE
;
1756 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_labeled_unicast
,
1757 address_family_ipv4_labeled_unicast_cmd
,
1758 "address-family ipv4 labeled-unicast",
1759 "Enter Address Family command mode\n"
1761 "Address Family modifier\n")
1763 vty
->node
= BGP_IPV4L_NODE
;
1767 DEFUNSH(VTYSH_BGPD
, address_family_ipv6
, address_family_ipv6_cmd
,
1768 "address-family ipv6 [unicast]",
1769 "Enter Address Family command mode\n"
1771 "Address Family modifier\n")
1773 vty
->node
= BGP_IPV6_NODE
;
1777 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_multicast
,
1778 address_family_ipv6_multicast_cmd
, "address-family ipv6 multicast",
1779 "Enter Address Family command mode\n"
1781 "Address Family modifier\n")
1783 vty
->node
= BGP_IPV6M_NODE
;
1787 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_vpn
, address_family_ipv6_vpn_cmd
,
1788 "address-family ipv6 vpn",
1789 "Enter Address Family command mode\n"
1791 "Address Family modifier\n")
1793 vty
->node
= BGP_VPNV6_NODE
;
1797 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_labeled_unicast
,
1798 address_family_ipv6_labeled_unicast_cmd
,
1799 "address-family ipv6 labeled-unicast",
1800 "Enter Address Family command mode\n"
1802 "Address Family modifier\n")
1804 vty
->node
= BGP_IPV6L_NODE
;
1812 "Enable rpki and enter rpki configuration mode\n")
1814 vty
->node
= RPKI_NODE
;
1821 "bmp targets BMPTARGETS",
1822 "BGP Monitoring Protocol\n"
1823 "Create BMP target group\n"
1824 "Name of the BMP target group\n")
1826 vty
->node
= BMP_NODE
;
1833 "segment-routing srv6",
1834 "Segment-Routing configuration\n"
1835 "Segment-Routing SRv6 configuration\n")
1837 vty
->node
= BGP_SRV6_NODE
;
1845 "exit Segment-Routing SRv6 configuration\n")
1847 if (vty
->node
== BGP_SRV6_NODE
)
1848 vty
->node
= BGP_NODE
;
1856 "quit Segment-Routing SRv6 configuration\n")
1858 if (vty
->node
== BGP_SRV6_NODE
)
1859 vty
->node
= BGP_NODE
;
1863 DEFUNSH(VTYSH_BGPD
, address_family_evpn
, address_family_evpn_cmd
,
1864 "address-family <l2vpn evpn>",
1865 "Enter Address Family command mode\n"
1867 "Address Family modifier\n")
1869 vty
->node
= BGP_EVPN_NODE
;
1873 DEFUNSH(VTYSH_BGPD
, bgp_evpn_vni
, bgp_evpn_vni_cmd
, "vni " CMD_VNI_RANGE
,
1874 "VXLAN Network Identifier\n"
1877 vty
->node
= BGP_EVPN_VNI_NODE
;
1881 #if defined(ENABLE_BGP_VNC)
1882 DEFUNSH(VTYSH_BGPD
, vnc_defaults
, vnc_defaults_cmd
, "vnc defaults",
1883 "VNC/RFP related configuration\n"
1884 "Configure default NVE group\n")
1886 vty
->node
= BGP_VNC_DEFAULTS_NODE
;
1890 DEFUNSH(VTYSH_BGPD
, vnc_nve_group
, vnc_nve_group_cmd
, "vnc nve-group NAME",
1891 "VNC/RFP related configuration\n"
1892 "Configure a NVE group\n"
1895 vty
->node
= BGP_VNC_NVE_GROUP_NODE
;
1899 DEFUNSH(VTYSH_BGPD
, vnc_vrf_policy
, vnc_vrf_policy_cmd
, "vrf-policy NAME",
1900 "Configure a VRF policy group\n"
1903 vty
->node
= BGP_VRF_POLICY_NODE
;
1907 DEFUNSH(VTYSH_BGPD
, vnc_l2_group
, vnc_l2_group_cmd
, "vnc l2-group NAME",
1908 "VNC/RFP related configuration\n"
1909 "Configure a L2 group\n"
1912 vty
->node
= BGP_VNC_L2_GROUP_NODE
;
1916 DEFUNSH(VTYSH_BGPD
, exit_vnc_config
, exit_vnc_config_cmd
, "exit-vnc",
1917 "Exit from VNC configuration mode\n")
1919 if (vty
->node
== BGP_VNC_DEFAULTS_NODE
1920 || vty
->node
== BGP_VNC_NVE_GROUP_NODE
1921 || vty
->node
== BGP_VNC_L2_GROUP_NODE
)
1922 vty
->node
= BGP_NODE
;
1926 DEFUNSH(VTYSH_BGPD
, exit_vrf_policy
, exit_vrf_policy_cmd
, "exit-vrf-policy",
1927 "Exit from VRF policy configuration mode\n")
1929 if (vty
->node
== BGP_VRF_POLICY_NODE
)
1930 vty
->node
= BGP_NODE
;
1934 #endif /* HAVE_BGPD */
1936 DEFUNSH(VTYSH_KEYS
, key_chain
, key_chain_cmd
, "key chain WORD",
1937 "Authentication key management\n"
1938 "Key-chain management\n"
1941 vty
->node
= KEYCHAIN_NODE
;
1945 DEFUNSH(VTYSH_KEYS
, key
, key_cmd
, "key (0-2147483647)",
1947 "Key identifier number\n")
1949 vty
->node
= KEYCHAIN_KEY_NODE
;
1954 DEFUNSH(VTYSH_RIPD
, router_rip
, router_rip_cmd
, "router rip [vrf NAME]",
1955 ROUTER_STR
"RIP\n" VRF_CMD_HELP_STR
)
1957 vty
->node
= RIP_NODE
;
1960 #endif /* HAVE_RIPD */
1963 DEFUNSH(VTYSH_RIPNGD
, router_ripng
, router_ripng_cmd
, "router ripng [vrf NAME]",
1964 ROUTER_STR
"RIPng\n" VRF_CMD_HELP_STR
)
1966 vty
->node
= RIPNG_NODE
;
1969 #endif /* HAVE_RIPNGD */
1972 DEFUNSH(VTYSH_OSPFD
, router_ospf
, router_ospf_cmd
,
1973 "router ospf [(1-65535)] [vrf NAME]",
1974 "Enable a routing process\n"
1975 "Start OSPF configuration\n"
1979 vty
->node
= OSPF_NODE
;
1982 #endif /* HAVE_OSPFD */
1985 DEFUNSH(VTYSH_EIGRPD
, router_eigrp
, router_eigrp_cmd
, "router eigrp (1-65535) [vrf NAME]",
1986 "Enable a routing process\n"
1987 "Start EIGRP configuration\n"
1988 "AS number to use\n"
1991 vty
->node
= EIGRP_NODE
;
1994 #endif /* HAVE_EIGRPD */
1997 DEFUNSH(VTYSH_BABELD
, router_babel
, router_babel_cmd
, "router babel",
1998 "Enable a routing process\n"
1999 "Make Babel instance command\n")
2001 vty
->node
= BABEL_NODE
;
2004 #endif /* HAVE_BABELD */
2007 DEFUNSH(VTYSH_OSPF6D
, router_ospf6
, router_ospf6_cmd
, "router ospf6 [vrf NAME]",
2008 ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR
)
2010 vty
->node
= OSPF6_NODE
;
2015 #if defined(HAVE_LDPD)
2016 DEFUNSH(VTYSH_LDPD
, ldp_mpls_ldp
, ldp_mpls_ldp_cmd
, "mpls ldp",
2017 "Global MPLS configuration subcommands\n"
2018 "Label Distribution Protocol\n")
2020 vty
->node
= LDP_NODE
;
2024 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv4
, ldp_address_family_ipv4_cmd
,
2025 "address-family ipv4",
2026 "Configure Address Family and its parameters\n"
2029 vty
->node
= LDP_IPV4_NODE
;
2033 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv6
, ldp_address_family_ipv6_cmd
,
2034 "address-family ipv6",
2035 "Configure Address Family and its parameters\n"
2038 vty
->node
= LDP_IPV6_NODE
;
2042 DEFUNSH(VTYSH_LDPD
, ldp_exit_address_family
, ldp_exit_address_family_cmd
,
2043 "exit-address-family", "Exit from Address Family configuration mode\n")
2045 if (vty
->node
== LDP_IPV4_NODE
|| vty
->node
== LDP_IPV6_NODE
)
2046 vty
->node
= LDP_NODE
;
2050 DEFUNSH(VTYSH_LDPD
, ldp_interface_ifname
, ldp_interface_ifname_cmd
,
2052 "Enable LDP on an interface and enter interface submode\n"
2053 "Interface's name\n")
2055 switch (vty
->node
) {
2057 vty
->node
= LDP_IPV4_IFACE_NODE
;
2060 vty
->node
= LDP_IPV6_IFACE_NODE
;
2069 DEFUNSH(VTYSH_LDPD
, ldp_l2vpn_word_type_vpls
, ldp_l2vpn_word_type_vpls_cmd
,
2070 "l2vpn WORD type vpls",
2071 "Configure l2vpn commands\n"
2074 "Virtual Private LAN Service\n")
2076 vty
->node
= LDP_L2VPN_NODE
;
2080 DEFUNSH(VTYSH_LDPD
, ldp_member_pseudowire_ifname
,
2081 ldp_member_pseudowire_ifname_cmd
, "member pseudowire IFNAME",
2082 "L2VPN member configuration\n"
2083 "Pseudowire interface\n"
2084 "Interface's name\n")
2086 vty
->node
= LDP_PSEUDOWIRE_NODE
;
2092 DEFUNSH(VTYSH_ISISD
, router_isis
, router_isis_cmd
,
2093 "router isis WORD [vrf NAME]",
2096 "ISO Routing area tag\n" VRF_CMD_HELP_STR
)
2098 vty
->node
= ISIS_NODE
;
2101 #endif /* HAVE_ISISD */
2104 DEFUNSH(VTYSH_FABRICD
, router_openfabric
, router_openfabric_cmd
, "router openfabric WORD",
2106 "OpenFabric routing protocol\n"
2107 "ISO Routing area tag\n")
2109 vty
->node
= OPENFABRIC_NODE
;
2112 #endif /* HAVE_FABRICD */
2114 DEFUNSH(VTYSH_SR
, segment_routing
, segment_routing_cmd
,
2116 "Configure segment routing\n")
2118 vty
->node
= SEGMENT_ROUTING_NODE
;
2122 #if defined (HAVE_PATHD)
2123 DEFUNSH(VTYSH_PATHD
, sr_traffic_eng
, sr_traffic_eng_cmd
,
2125 "Configure SR traffic engineering\n")
2127 vty
->node
= SR_TRAFFIC_ENG_NODE
;
2131 DEFUNSH(VTYSH_PATHD
, srte_segment_list
, srte_segment_list_cmd
,
2132 "segment-list WORD$name",
2134 "Segment List Name\n")
2136 vty
->node
= SR_SEGMENT_LIST_NODE
;
2140 DEFUNSH(VTYSH_PATHD
, srte_policy
, srte_policy_cmd
,
2141 "policy color (0-4294967295) endpoint <A.B.C.D|X:X::X:X>",
2142 "Segment Routing Policy\n"
2144 "SR Policy color value\n"
2145 "SR Policy endpoint\n"
2146 "SR Policy endpoint IPv4 address\n"
2147 "SR Policy endpoint IPv6 address\n")
2149 vty
->node
= SR_POLICY_NODE
;
2153 DEFUNSH(VTYSH_PATHD
, srte_policy_candidate_dyn_path
,
2154 srte_policy_candidate_dyn_path_cmd
,
2155 "candidate-path preference (0-4294967295) name WORD dynamic",
2156 "Segment Routing Policy Candidate Path\n"
2157 "Segment Routing Policy Candidate Path Preference\n"
2158 "Administrative Preference\n"
2159 "Segment Routing Policy Candidate Path Name\n"
2163 vty
->node
= SR_CANDIDATE_DYN_NODE
;
2167 DEFUNSH(VTYSH_PATHD
, pcep
, pcep_cmd
,
2169 "Configure SR pcep\n")
2171 vty
->node
= PCEP_NODE
;
2175 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcc
, pcep_cli_pcc_cmd
,
2177 "PCC configuration\n")
2179 vty
->node
= PCEP_PCC_NODE
;
2183 DEFUNSH(VTYSH_PATHD
, pcep_cli_pce
, pcep_cli_pce_cmd
,
2185 "PCE configuration\n"
2188 vty
->node
= PCEP_PCE_NODE
;
2192 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcep_pce_config
, pcep_cli_pcep_pce_config_cmd
,
2194 "PCEP peer Configuration Group\n"
2195 "PCEP peer Configuration Group name\n")
2197 vty
->node
= PCEP_PCE_CONFIG_NODE
;
2201 #endif /* HAVE_PATHD */
2203 DEFUNSH(VTYSH_RMAP
, vtysh_route_map
, vtysh_route_map_cmd
,
2204 "route-map RMAP_NAME <deny|permit> (1-65535)",
2205 "Create route-map or enter route-map command mode\n"
2207 "Route map denies set operations\n"
2208 "Route map permits set operations\n"
2209 "Sequence to insert to/delete from existing route-map entry\n")
2211 vty
->node
= RMAP_NODE
;
2216 DEFUNSH(VTYSH_PBRD
, vtysh_pbr_map
, vtysh_pbr_map_cmd
,
2217 "pbr-map PBRMAP seq (1-700)",
2218 "Create pbr-map or enter pbr-map command mode\n"
2219 "The name of the PBR MAP\n"
2220 "Sequence to insert to/delete from existing pbr-map entry\n"
2221 "Sequence number\n")
2223 vty
->node
= PBRMAP_NODE
;
2227 DEFSH(VTYSH_PBRD
, vtysh_no_pbr_map_cmd
, "no pbr-map PBRMAP [seq (1-700)]",
2230 "The name of the PBR MAP\n"
2231 "Sequence to delete from existing pbr-map entry\n"
2232 "Sequence number\n")
2233 #endif /* HAVE_PBRD */
2236 DEFUNSH(VTYSH_BFDD
, bfd_enter
, bfd_enter_cmd
, "bfd", "Configure BFD peers\n")
2238 vty
->node
= BFD_NODE
;
2242 DEFUNSH(VTYSH_BFDD
, bfd_peer_enter
, bfd_peer_enter_cmd
,
2243 "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
2245 "IPv4 peer address\n"
2246 "IPv6 peer address\n"
2247 "Configure multihop\n"
2248 "Configure local address\n"
2249 "IPv4 local address\n"
2250 "IPv6 local address\n"
2252 "Configure interface name to use\n"
2254 "Configure VRF name\n")
2256 vty
->node
= BFD_PEER_NODE
;
2260 DEFUNSH(VTYSH_BFDD
, bfd_profile_enter
, bfd_profile_enter_cmd
,
2263 BFD_PROFILE_NAME_STR
)
2265 vty
->node
= BFD_PROFILE_NODE
;
2268 #endif /* HAVE_BFDD */
2270 DEFUNSH(VTYSH_ALL
, vtysh_line_vty
, vtysh_line_vty_cmd
, "line vty",
2271 "Configure a terminal line\n"
2272 "Virtual terminal\n")
2274 vty
->node
= VTY_NODE
;
2278 DEFUNSH(VTYSH_REALLYALL
, vtysh_enable
, vtysh_enable_cmd
, "enable",
2279 "Turn on privileged mode command\n")
2281 vty
->node
= ENABLE_NODE
;
2285 DEFUNSH(VTYSH_REALLYALL
, vtysh_disable
, vtysh_disable_cmd
, "disable",
2286 "Turn off privileged mode command\n")
2288 if (vty
->node
== ENABLE_NODE
)
2289 vty
->node
= VIEW_NODE
;
2293 DEFUNSH(VTYSH_REALLYALL
, vtysh_config_terminal
, vtysh_config_terminal_cmd
,
2294 "configure [terminal]",
2295 "Configuration from vty interface\n"
2296 "Configuration terminal\n")
2298 vty
->node
= CONFIG_NODE
;
2302 static int vtysh_exit(struct vty
*vty
)
2304 struct cmd_node
*cnode
= vector_lookup(cmdvec
, vty
->node
);
2306 if (vty
->node
== VIEW_NODE
|| vty
->node
== ENABLE_NODE
)
2308 if (cnode
->node_exit
)
2309 cnode
->node_exit(vty
);
2310 if (cnode
->parent_node
)
2311 vty
->node
= cnode
->parent_node
;
2313 if (vty
->node
== CONFIG_NODE
) {
2314 /* resync in case one of the daemons is somewhere else */
2315 vtysh_execute("end");
2316 vtysh_execute("configure");
2321 DEFUNSH(VTYSH_REALLYALL
, vtysh_exit_all
, vtysh_exit_all_cmd
, "exit",
2322 "Exit current mode and down to previous mode\n")
2324 return vtysh_exit(vty
);
2327 DEFUNSH(VTYSH_REALLYALL
, vtysh_quit_all
, vtysh_quit_all_cmd
, "quit",
2328 "Exit current mode and down to previous mode\n")
2330 return vtysh_exit_all(self
, vty
, argc
, argv
);
2334 DEFUNSH(VTYSH_BGPD
, exit_address_family
, exit_address_family_cmd
,
2335 "exit-address-family", "Exit from Address Family configuration mode\n")
2337 if (vty
->node
== BGP_IPV4_NODE
|| vty
->node
== BGP_IPV4M_NODE
2338 || vty
->node
== BGP_IPV4L_NODE
|| vty
->node
== BGP_VPNV4_NODE
2339 || vty
->node
== BGP_VPNV6_NODE
|| vty
->node
== BGP_IPV6_NODE
2340 || vty
->node
== BGP_IPV6L_NODE
|| vty
->node
== BGP_IPV6M_NODE
2341 || vty
->node
== BGP_EVPN_NODE
2342 || vty
->node
== BGP_FLOWSPECV4_NODE
2343 || vty
->node
== BGP_FLOWSPECV6_NODE
)
2344 vty
->node
= BGP_NODE
;
2348 DEFUNSH(VTYSH_BGPD
, exit_vni
, exit_vni_cmd
, "exit-vni", "Exit from VNI mode\n")
2350 if (vty
->node
== BGP_EVPN_VNI_NODE
)
2351 vty
->node
= BGP_EVPN_NODE
;
2355 DEFUNSH(VTYSH_BGPD
, rpki_exit
, rpki_exit_cmd
, "exit",
2356 "Exit current mode and down to previous mode\n")
2362 DEFUNSH(VTYSH_BGPD
, rpki_quit
, rpki_quit_cmd
, "quit",
2363 "Exit current mode and down to previous mode\n")
2365 return rpki_exit(self
, vty
, argc
, argv
);
2368 DEFUNSH(VTYSH_BGPD
, bmp_exit
, bmp_exit_cmd
, "exit",
2369 "Exit current mode and down to previous mode\n")
2375 DEFUNSH(VTYSH_BGPD
, bmp_quit
, bmp_quit_cmd
, "quit",
2376 "Exit current mode and down to previous mode\n")
2378 return bmp_exit(self
, vty
, argc
, argv
);
2380 #endif /* HAVE_BGPD */
2382 DEFUNSH(VTYSH_VRF
, exit_vrf_config
, exit_vrf_config_cmd
, "exit-vrf",
2383 "Exit from VRF configuration mode\n")
2385 if (vty
->node
== VRF_NODE
)
2386 vty
->node
= CONFIG_NODE
;
2390 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_config
, exit_srv6_config_cmd
, "exit",
2391 "Exit from SRv6 configuration mode\n")
2393 if (vty
->node
== SRV6_NODE
)
2394 vty
->node
= SEGMENT_ROUTING_NODE
;
2398 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_locs_config
, exit_srv6_locs_config_cmd
, "exit",
2399 "Exit from SRv6-locator configuration mode\n")
2401 if (vty
->node
== SRV6_LOCS_NODE
)
2402 vty
->node
= SRV6_NODE
;
2406 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_loc_config
, exit_srv6_loc_config_cmd
, "exit",
2407 "Exit from SRv6-locators configuration mode\n")
2409 if (vty
->node
== SRV6_LOC_NODE
)
2410 vty
->node
= SRV6_LOCS_NODE
;
2415 DEFUNSH(VTYSH_RIPD
, vtysh_exit_ripd
, vtysh_exit_ripd_cmd
, "exit",
2416 "Exit current mode and down to previous mode\n")
2418 return vtysh_exit(vty
);
2421 DEFUNSH(VTYSH_RIPD
, vtysh_quit_ripd
, vtysh_quit_ripd_cmd
, "quit",
2422 "Exit current mode and down to previous mode\n")
2424 return vtysh_exit_ripd(self
, vty
, argc
, argv
);
2426 #endif /* HAVE_RIPD */
2429 DEFUNSH(VTYSH_RIPNGD
, vtysh_exit_ripngd
, vtysh_exit_ripngd_cmd
, "exit",
2430 "Exit current mode and down to previous mode\n")
2432 return vtysh_exit(vty
);
2435 DEFUNSH(VTYSH_RIPNGD
, vtysh_quit_ripngd
, vtysh_quit_ripngd_cmd
, "quit",
2436 "Exit current mode and down to previous mode\n")
2438 return vtysh_exit_ripngd(self
, vty
, argc
, argv
);
2440 #endif /* HAVE_RIPNGD */
2442 DEFUNSH(VTYSH_RMAP
, vtysh_exit_rmap
, vtysh_exit_rmap_cmd
, "exit",
2443 "Exit current mode and down to previous mode\n")
2445 return vtysh_exit(vty
);
2448 DEFUNSH(VTYSH_RMAP
, vtysh_quit_rmap
, vtysh_quit_rmap_cmd
, "quit",
2449 "Exit current mode and down to previous mode\n")
2451 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2455 DEFUNSH(VTYSH_PBRD
, vtysh_exit_pbr_map
, vtysh_exit_pbr_map_cmd
, "exit",
2456 "Exit current mode and down to previous mode\n")
2458 return vtysh_exit(vty
);
2461 DEFUNSH(VTYSH_PBRD
, vtysh_quit_pbr_map
, vtysh_quit_pbr_map_cmd
, "quit",
2462 "Exit current mode and down to previous mode\n")
2464 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2466 #endif /* HAVE_PBRD */
2469 DEFUNSH(VTYSH_BGPD
, vtysh_exit_bgpd
, vtysh_exit_bgpd_cmd
, "exit",
2470 "Exit current mode and down to previous mode\n")
2472 return vtysh_exit(vty
);
2475 DEFUNSH(VTYSH_BGPD
, vtysh_quit_bgpd
, vtysh_quit_bgpd_cmd
, "quit",
2476 "Exit current mode and down to previous mode\n")
2478 return vtysh_exit_bgpd(self
, vty
, argc
, argv
);
2480 #endif /* HAVE_BGPD */
2483 DEFUNSH(VTYSH_OSPFD
, vtysh_exit_ospfd
, vtysh_exit_ospfd_cmd
, "exit",
2484 "Exit current mode and down to previous mode\n")
2486 return vtysh_exit(vty
);
2489 DEFUNSH(VTYSH_OSPFD
, vtysh_quit_ospfd
, vtysh_quit_ospfd_cmd
, "quit",
2490 "Exit current mode and down to previous mode\n")
2492 return vtysh_exit_ospfd(self
, vty
, argc
, argv
);
2494 #endif /* HAVE_OSPFD */
2497 DEFUNSH(VTYSH_EIGRPD
, vtysh_exit_eigrpd
, vtysh_exit_eigrpd_cmd
, "exit",
2498 "Exit current mode and down to previous mode\n")
2500 return vtysh_exit(vty
);
2503 DEFUNSH(VTYSH_EIGRPD
, vtysh_quit_eigrpd
, vtysh_quit_eigrpd_cmd
, "quit",
2504 "Exit current mode and down to previous mode\n")
2506 return vtysh_exit(vty
);
2508 #endif /* HAVE_EIGRPD */
2511 DEFUNSH(VTYSH_BABELD
, vtysh_exit_babeld
, vtysh_exit_babeld_cmd
, "exit",
2512 "Exit current mode and down to previous mode\n")
2514 return vtysh_exit(vty
);
2517 DEFUNSH(VTYSH_BABELD
, vtysh_quit_babeld
, vtysh_quit_babeld_cmd
, "quit",
2518 "Exit current mode and down to previous mode\n")
2520 return vtysh_exit(vty
);
2522 #endif /* HAVE_BABELD */
2525 DEFUNSH(VTYSH_OSPF6D
, vtysh_exit_ospf6d
, vtysh_exit_ospf6d_cmd
, "exit",
2526 "Exit current mode and down to previous mode\n")
2528 return vtysh_exit(vty
);
2531 DEFUNSH(VTYSH_OSPF6D
, vtysh_quit_ospf6d
, vtysh_quit_ospf6d_cmd
, "quit",
2532 "Exit current mode and down to previous mode\n")
2534 return vtysh_exit_ospf6d(self
, vty
, argc
, argv
);
2536 #endif /* HAVE_OSPF6D */
2538 #if defined(HAVE_LDPD)
2539 DEFUNSH(VTYSH_LDPD
, vtysh_exit_ldpd
, vtysh_exit_ldpd_cmd
, "exit",
2540 "Exit current mode and down to previous mode\n")
2542 return vtysh_exit(vty
);
2545 ALIAS(vtysh_exit_ldpd
, vtysh_quit_ldpd_cmd
, "quit",
2546 "Exit current mode and down to previous mode\n")
2550 DEFUNSH(VTYSH_ISISD
, vtysh_exit_isisd
, vtysh_exit_isisd_cmd
, "exit",
2551 "Exit current mode and down to previous mode\n")
2553 return vtysh_exit(vty
);
2556 DEFUNSH(VTYSH_ISISD
, vtysh_quit_isisd
, vtysh_quit_isisd_cmd
, "quit",
2557 "Exit current mode and down to previous mode\n")
2559 return vtysh_exit_isisd(self
, vty
, argc
, argv
);
2561 #endif /* HAVE_ISISD */
2564 DEFUNSH(VTYSH_BFDD
, vtysh_exit_bfdd
, vtysh_exit_bfdd_cmd
, "exit",
2565 "Exit current mode and down to previous mode\n")
2567 return vtysh_exit(vty
);
2570 ALIAS(vtysh_exit_bfdd
, vtysh_quit_bfdd_cmd
, "quit",
2571 "Exit current mode and down to previous mode\n")
2575 DEFUNSH(VTYSH_FABRICD
, vtysh_exit_fabricd
, vtysh_exit_fabricd_cmd
, "exit",
2576 "Exit current mode and down to previous mode\n")
2578 return vtysh_exit(vty
);
2581 DEFUNSH(VTYSH_FABRICD
, vtysh_quit_fabricd
, vtysh_quit_fabricd_cmd
, "quit",
2582 "Exit current mode and down to previous mode\n")
2584 return vtysh_exit_fabricd(self
, vty
, argc
, argv
);
2586 #endif /* HAVE_FABRICD */
2588 DEFUNSH(VTYSH_KEYS
, vtysh_exit_keys
, vtysh_exit_keys_cmd
, "exit",
2589 "Exit current mode and down to previous mode\n")
2591 return vtysh_exit(vty
);
2594 DEFUNSH(VTYSH_KEYS
, vtysh_quit_keys
, vtysh_quit_keys_cmd
, "quit",
2595 "Exit current mode and down to previous mode\n")
2597 return vtysh_exit_keys(self
, vty
, argc
, argv
);
2600 DEFUNSH(VTYSH_SR
, vtysh_exit_sr
, vtysh_exit_sr_cmd
, "exit",
2601 "Exit current mode and down to previous mode\n")
2603 return vtysh_exit(vty
);
2606 DEFUNSH(VTYSH_SR
, vtysh_quit_sr
, vtysh_quit_sr_cmd
, "quit",
2607 "Exit current mode and down to previous mode\n")
2609 return vtysh_exit(vty
);
2612 #if defined(HAVE_PATHD)
2613 DEFUNSH(VTYSH_PATHD
, vtysh_exit_pathd
, vtysh_exit_pathd_cmd
, "exit",
2614 "Exit current mode and down to previous mode\n")
2616 return vtysh_exit(vty
);
2619 DEFUNSH(VTYSH_PATHD
, vtysh_quit_pathd
, vtysh_quit_pathd_cmd
, "quit",
2620 "Exit current mode and down to previous mode\n")
2622 return vtysh_exit_pathd(self
, vty
, argc
, argv
);
2624 #endif /* HAVE_PATHD */
2626 DEFUNSH(VTYSH_ALL
, vtysh_exit_line_vty
, vtysh_exit_line_vty_cmd
, "exit",
2627 "Exit current mode and down to previous mode\n")
2629 return vtysh_exit(vty
);
2632 DEFUNSH(VTYSH_ALL
, vtysh_quit_line_vty
, vtysh_quit_line_vty_cmd
, "quit",
2633 "Exit current mode and down to previous mode\n")
2635 return vtysh_exit_line_vty(self
, vty
, argc
, argv
);
2638 DEFUNSH(VTYSH_INTERFACE
, vtysh_interface
, vtysh_interface_cmd
,
2639 "interface IFNAME [vrf NAME]",
2640 "Select an interface to configure\n"
2641 "Interface's name\n" VRF_CMD_HELP_STR
)
2643 vty
->node
= INTERFACE_NODE
;
2647 DEFUNSH(VTYSH_ZEBRA
, vtysh_pseudowire
, vtysh_pseudowire_cmd
,
2648 "pseudowire IFNAME",
2649 "Static pseudowire configuration\n"
2650 "Pseudowire name\n")
2652 vty
->node
= PW_NODE
;
2656 DEFUNSH(VTYSH_NH_GROUP
,
2657 vtysh_nexthop_group
, vtysh_nexthop_group_cmd
,
2658 "nexthop-group NHGNAME",
2659 "Nexthop Group configuration\n"
2660 "Name of the Nexthop Group\n")
2662 vty
->node
= NH_GROUP_NODE
;
2666 DEFSH(VTYSH_NH_GROUP
, vtysh_no_nexthop_group_cmd
,
2667 "no nexthop-group NHGNAME",
2669 "Nexthop Group Configuration\n"
2670 "Name of the Nexthop Group\n")
2672 DEFUNSH(VTYSH_VRF
, vtysh_vrf
, vtysh_vrf_cmd
, "vrf NAME",
2673 "Select a VRF to configure\n"
2676 vty
->node
= VRF_NODE
;
2680 DEFUNSH(VTYSH_VRF
, vtysh_exit_vrf
, vtysh_exit_vrf_cmd
, "exit",
2681 "Exit current mode and down to previous mode\n")
2683 return vtysh_exit(vty
);
2686 DEFUNSH(VTYSH_VRF
, vtysh_quit_vrf
, vtysh_quit_vrf_cmd
, "quit",
2687 "Exit current mode and down to previous mode\n")
2689 return vtysh_exit_vrf(self
, vty
, argc
, argv
);
2692 DEFUNSH(VTYSH_NH_GROUP
,
2693 vtysh_exit_nexthop_group
, vtysh_exit_nexthop_group_cmd
,
2694 "exit", "Exit current mode and down to previous mode\n")
2696 return vtysh_exit(vty
);
2699 DEFUNSH(VTYSH_NH_GROUP
,
2700 vtysh_quit_nexthop_group
, vtysh_quit_nexthop_group_cmd
,
2701 "quit", "Exit current mode and down to previous mode\n")
2703 return vtysh_exit_nexthop_group(self
, vty
, argc
, argv
);
2706 DEFUNSH(VTYSH_INTERFACE
, vtysh_exit_interface
, vtysh_exit_interface_cmd
, "exit",
2707 "Exit current mode and down to previous mode\n")
2709 return vtysh_exit(vty
);
2712 DEFUNSH(VTYSH_INTERFACE
, vtysh_quit_interface
, vtysh_quit_interface_cmd
, "quit",
2713 "Exit current mode and down to previous mode\n")
2715 return vtysh_exit_interface(self
, vty
, argc
, argv
);
2718 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_pseudowire
, vtysh_exit_pseudowire_cmd
, "exit",
2719 "Exit current mode and down to previous mode\n")
2721 return vtysh_exit(vty
);
2724 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_pseudowire
, vtysh_quit_pseudowire_cmd
, "quit",
2725 "Exit current mode and down to previous mode\n")
2727 return vtysh_exit_pseudowire(self
, vty
, argc
, argv
);
2730 static char *do_prepend(struct vty
*vty
, struct cmd_token
**argv
, int argc
)
2732 const char *argstr
[argc
+ 1];
2735 if (vty
->node
!= VIEW_NODE
) {
2740 for (i
= 0; i
< argc
; i
++)
2741 argstr
[i
+ off
] = argv
[i
]->arg
;
2743 return frrstr_join(argstr
, argc
+ off
, " ");
2746 static int show_per_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2747 const char *headline
)
2750 int ret
= CMD_SUCCESS
;
2751 char *line
= do_prepend(vty
, argv
, argc
);
2753 for (i
= 0; i
< array_size(vtysh_client
); i
++)
2754 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
2755 vty_out(vty
, headline
, vtysh_client
[i
].name
);
2756 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
2760 XFREE(MTYPE_TMP
, line
);
2765 static int show_one_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2769 char *line
= do_prepend(vty
, argv
, argc
);
2771 ret
= vtysh_client_execute_name(name
, line
);
2773 XFREE(MTYPE_TMP
, line
);
2778 DEFUN (vtysh_show_thread_timer
,
2779 vtysh_show_thread_timer_cmd
,
2780 "show thread timers",
2782 "Thread information\n"
2783 "Show all timers and how long they have in the system\n")
2785 return show_per_daemon(vty
, argv
, argc
, "Thread timers for %s:\n");
2788 DEFUN (vtysh_show_poll
,
2789 vtysh_show_poll_cmd
,
2792 "Thread information\n"
2793 "Thread Poll Information\n")
2795 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2798 DEFUN (vtysh_show_thread
,
2799 vtysh_show_thread_cmd
,
2800 "show thread cpu [FILTER]",
2802 "Thread information\n"
2803 "Thread CPU usage\n"
2804 "Display filter (rwtexb)\n")
2806 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2809 DEFUN (vtysh_show_work_queues
,
2810 vtysh_show_work_queues_cmd
,
2813 "Work Queue information\n")
2815 return show_per_daemon(vty
, argv
, argc
,
2816 "Work queue statistics for %s:\n");
2819 DEFUN (vtysh_show_work_queues_daemon
,
2820 vtysh_show_work_queues_daemon_cmd
,
2821 "show work-queues " DAEMONS_LIST
,
2823 "Work Queue information\n"
2826 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2829 DEFUNSH(VTYSH_ZEBRA
, vtysh_link_params
, vtysh_link_params_cmd
, "link-params",
2832 vty
->node
= LINK_PARAMS_NODE
;
2836 DEFUNSH(VTYSH_ZEBRA
, exit_link_params
, exit_link_params_cmd
, "exit-link-params",
2837 "Exit from Link Params configuration node\n")
2839 if (vty
->node
== LINK_PARAMS_NODE
)
2840 vty
->node
= INTERFACE_NODE
;
2844 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_link_params
, vtysh_exit_link_params_cmd
, "exit",
2845 "Exit current mode and down to previous mode\n")
2847 if (vty
->node
== LINK_PARAMS_NODE
)
2848 vty
->node
= INTERFACE_NODE
;
2852 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_link_params
, vtysh_quit_link_params_cmd
, "quit",
2853 "Exit current mode and down to previous mode\n")
2855 return vtysh_exit_link_params(self
, vty
, argc
, argv
);
2858 DEFUNSH_HIDDEN (0x00,
2860 vtysh_debug_all_cmd
,
2864 "Toggle all debugs on or off\n")
2869 DEFUN (vtysh_show_debugging
,
2870 vtysh_show_debugging_cmd
,
2875 return show_per_daemon(vty
, argv
, argc
, "");
2878 DEFUN (vtysh_show_debugging_hashtable
,
2879 vtysh_show_debugging_hashtable_cmd
,
2880 "show debugging hashtable [statistics]",
2883 "Statistics about hash tables\n"
2884 "Statistics about hash tables\n")
2886 bool stats
= strmatch(argv
[argc
- 1]->text
, "statistics");
2890 "Load factor (LF) - average number of elements across all buckets\n");
2892 "Full load factor (FLF) - average number of elements across full buckets\n\n");
2894 "Standard deviation (SD) is calculated for both the LF and FLF\n");
2896 "and indicates the typical deviation of bucket chain length\n");
2897 vty_out(vty
, "from the value in the corresponding load factor.\n\n");
2899 return show_per_daemon(vty
, argv
, stats
? argc
- 1 : argc
,
2900 "Hashtable statistics for %s:\n");
2903 DEFUN (vtysh_show_error_code
,
2904 vtysh_show_error_code_cmd
,
2905 "show error <(1-4294967296)|all> [json]",
2907 "Information on errors\n"
2908 "Error code to get info about\n"
2909 "Information on all errors\n"
2914 if (!strmatch(argv
[2]->text
, "all"))
2915 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2917 /* If it's not a shared code, send it to all the daemons */
2918 if (arg
< LIB_FERR_START
|| arg
> LIB_FERR_END
) {
2919 show_per_daemon(vty
, argv
, argc
, "");
2920 /* Otherwise, print it ourselves to avoid duplication */
2922 bool json
= strmatch(argv
[argc
- 1]->text
, "json");
2924 if (!strmatch(argv
[2]->text
, "all"))
2925 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2927 log_ref_display(vty
, arg
, json
);
2934 DEFUN_HIDDEN (show_config_running
,
2935 show_config_running_cmd
,
2936 "show configuration running\
2937 [<json|xml> [translate WORD]]\
2938 [with-defaults]" DAEMONS_LIST
,
2940 "Configuration information\n"
2941 "Running configuration\n"
2942 "Change output format to JSON\n"
2943 "Change output format to XML\n"
2944 "Translate output\n"
2945 "YANG module translator\n"
2946 "Show default values\n"
2949 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2952 DEFUN (show_yang_operational_data
,
2953 show_yang_operational_data_cmd
,
2954 "show yang operational-data XPATH\
2961 "YANG information\n"
2962 "Show YANG operational data\n"
2963 "XPath expression specifying the YANG data path\n"
2964 "Set the output format\n"
2965 "JavaScript Object Notation\n"
2966 "Extensible Markup Language\n"
2967 "Translate operational data\n"
2968 "YANG module translator\n"
2969 "Merge configuration data\n"
2972 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2975 DEFUN(show_yang_module
, show_yang_module_cmd
,
2976 "show yang module [module-translator WORD] " DAEMONS_LIST
,
2978 "YANG information\n"
2979 "Show loaded modules\n"
2980 "YANG module translator\n"
2981 "YANG module translator\n" DAEMONS_STR
)
2983 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2986 DEFUN(show_yang_module_detail
, show_yang_module_detail_cmd
,
2988 [module-translator WORD]\
2989 WORD <compiled|summary|tree|yang|yin> " DAEMONS_LIST
,
2991 "YANG information\n"
2992 "Show loaded modules\n"
2993 "YANG module translator\n"
2994 "YANG module translator\n"
2996 "Display compiled module in YANG format\n"
2997 "Display summary information about the module\n"
2998 "Display module in the tree (RFC 8340) format\n"
2999 "Display module in the YANG format\n"
3000 "Display module in the YIN format\n" DAEMONS_STR
)
3002 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3006 DEFUNSH(VTYSH_ALL
, debug_nb
,
3008 "[no] debug northbound\
3010 callbacks [{configuration|state|rpc}]\
3017 "Northbound debugging\n"
3024 "libyang debugging\n")
3029 DEFUN (vtysh_show_history
,
3030 vtysh_show_history_cmd
,
3033 "The list of commands stored in history\n")
3035 HIST_ENTRY
**hlist
= history_list();
3039 vty_out(vty
, "%s\n", hlist
[i
]->line
);
3046 DEFUN (vtysh_show_memory
,
3047 vtysh_show_memory_cmd
,
3048 "show memory [" DAEMONS_LIST
"]",
3050 "Memory statistics\n"
3054 return show_one_daemon(vty
, argv
, argc
- 1,
3055 argv
[argc
- 1]->text
);
3057 return show_per_daemon(vty
, argv
, argc
, "Memory statistics for %s:\n");
3060 DEFUN (vtysh_show_modules
,
3061 vtysh_show_modules_cmd
,
3066 return show_per_daemon(vty
, argv
, argc
, "Module information for %s:\n");
3069 /* Logging commands. */
3070 DEFUN (vtysh_show_logging
,
3071 vtysh_show_logging_cmd
,
3074 "Show current logging configuration\n")
3076 return show_per_daemon(vty
, argv
, argc
,
3077 "Logging configuration for %s:\n");
3080 DEFUNSH(VTYSH_ALL
, vtysh_debug_memstats
,
3081 vtysh_debug_memstats_cmd
, "[no] debug memstats-at-exit",
3084 "Print memory statistics at exit\n")
3089 DEFUN(vtysh_debug_uid_backtrace
,
3090 vtysh_debug_uid_backtrace_cmd
,
3091 "[no] debug unique-id UID backtrace",
3094 "Options per individual log message, by unique ID\n"
3095 "Log message unique ID (XXXXX-XXXXX)\n"
3096 "Add backtrace to log when message is printed\n")
3098 unsigned int i
, ok
= 0;
3099 int err
= CMD_SUCCESS
, ret
;
3103 if (!strcmp(argv
[0]->text
, "no")) {
3105 snprintfrr(line
, sizeof(line
),
3106 "no debug unique-id %s backtrace", uid
);
3109 snprintfrr(line
, sizeof(line
), "debug unique-id %s backtrace",
3113 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3114 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
3115 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3120 case CMD_ERR_NOTHING_TODO
:
3121 /* ignore this daemon
3123 * note this doesn't need to handle instances
3124 * of the same daemon individually because
3125 * the same daemon will have the same UIDs
3129 if (err
== CMD_SUCCESS
)
3135 if (err
== CMD_SUCCESS
&& !ok
) {
3136 vty_out(vty
, "%% no running daemon recognizes unique-ID %s\n",
3143 DEFUNSH(VTYSH_ALL
, vtysh_service_password_encrypt
,
3144 vtysh_service_password_encrypt_cmd
, "service password-encryption",
3145 "Set up miscellaneous service\n"
3146 "Enable encrypted passwords\n")
3151 DEFUNSH(VTYSH_ALL
, no_vtysh_service_password_encrypt
,
3152 no_vtysh_service_password_encrypt_cmd
, "no service password-encryption",
3154 "Set up miscellaneous service\n"
3155 "Enable encrypted passwords\n")
3160 DEFUNSH(VTYSH_ALL
, vtysh_config_password
, vtysh_password_cmd
,
3161 "password [(8-8)] LINE",
3162 "Modify the terminal connection password\n"
3163 "Specifies a HIDDEN password will follow\n"
3164 "The password string\n")
3169 DEFUNSH(VTYSH_ALL
, no_vtysh_config_password
, no_vtysh_password_cmd
,
3170 "no password", NO_STR
3171 "Modify the terminal connection password\n")
3173 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3178 DEFUNSH(VTYSH_ALL
, vtysh_config_enable_password
, vtysh_enable_password_cmd
,
3179 "enable password [(8-8)] LINE",
3180 "Modify enable password parameters\n"
3181 "Assign the privileged level password\n"
3182 "Specifies a HIDDEN password will follow\n"
3183 "The 'enable' password string\n")
3188 DEFUNSH(VTYSH_ALL
, no_vtysh_config_enable_password
,
3189 no_vtysh_enable_password_cmd
, "no enable password", NO_STR
3190 "Modify enable password parameters\n"
3191 "Assign the privileged level password\n")
3193 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3198 DEFUN (vtysh_write_terminal
,
3199 vtysh_write_terminal_cmd
,
3200 "write terminal ["DAEMONS_LIST
"] [no-header]",
3201 "Write running configuration to memory, network, or terminal\n"
3202 "Write to terminal\n"
3204 "Skip \"Building configuration...\" header\n")
3207 char line
[] = "do write terminal";
3209 if (!strcmp(argv
[argc
- 1]->arg
, "no-header"))
3212 vty_out(vty
, "Building configuration...\n");
3213 vty_out(vty
, "\nCurrent configuration:\n");
3214 vty_out(vty
, "!\n");
3217 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3219 || (strmatch(vtysh_client
[i
].name
, argv
[2]->text
)))
3220 vtysh_client_config(&vtysh_client
[i
], line
);
3222 /* Integrate vtysh specific configuration. */
3223 vty_open_pager(vty
);
3224 vtysh_config_write();
3225 vtysh_config_dump();
3226 vty_close_pager(vty
);
3227 vty_out(vty
, "end\n");
3232 DEFUN (vtysh_show_running_config
,
3233 vtysh_show_running_config_cmd
,
3234 "show running-config ["DAEMONS_LIST
"] [no-header]",
3236 "Current operating configuration\n"
3238 "Skip \"Building configuration...\" header\n")
3240 return vtysh_write_terminal(self
, vty
, argc
, argv
);
3243 DEFUN (vtysh_integrated_config
,
3244 vtysh_integrated_config_cmd
,
3245 "service integrated-vtysh-config",
3246 "Set up miscellaneous service\n"
3247 "Write configuration into integrated file\n")
3249 vtysh_write_integrated
= WRITE_INTEGRATED_YES
;
3253 DEFUN (no_vtysh_integrated_config
,
3254 no_vtysh_integrated_config_cmd
,
3255 "no service integrated-vtysh-config",
3257 "Set up miscellaneous service\n"
3258 "Write configuration into integrated file\n")
3260 vtysh_write_integrated
= WRITE_INTEGRATED_NO
;
3264 static void backup_config_file(const char *fbackup
)
3266 char *integrate_sav
= NULL
;
3268 size_t integrate_sav_sz
= strlen(fbackup
) + strlen(CONF_BACKUP_EXT
) + 1;
3269 integrate_sav
= malloc(integrate_sav_sz
);
3270 strlcpy(integrate_sav
, fbackup
, integrate_sav_sz
);
3271 strlcat(integrate_sav
, CONF_BACKUP_EXT
, integrate_sav_sz
);
3273 /* Move current configuration file to backup config file. */
3274 if (unlink(integrate_sav
) != 0 && errno
!= ENOENT
)
3275 vty_out(vty
, "Unlink failed for %s: %s\n", integrate_sav
,
3277 if (rename(fbackup
, integrate_sav
) != 0 && errno
!= ENOENT
)
3278 vty_out(vty
, "Error renaming %s to %s: %s\n", fbackup
,
3279 integrate_sav
, strerror(errno
));
3280 free(integrate_sav
);
3283 int vtysh_write_config_integrated(void)
3286 char line
[] = "do write terminal";
3290 struct passwd
*pwentry
;
3293 struct group
*grentry
;
3300 vty_out(vty
, "Building Configuration...\n");
3302 backup_config_file(frr_config
);
3303 fp
= fopen(frr_config
, "w");
3306 "%% Error: failed to open configuration file %s: %s\n",
3307 frr_config
, safe_strerror(errno
));
3308 return CMD_WARNING_CONFIG_FAILED
;
3312 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3313 vtysh_client_config(&vtysh_client
[i
], line
);
3315 vtysh_config_write();
3316 vty
->of_saved
= vty
->of
;
3318 vtysh_config_dump();
3319 vty
->of
= vty
->of_saved
;
3321 if (fchmod(fd
, CONFIGFILE_MASK
) != 0) {
3322 printf("%% Warning: can't chmod configuration file %s: %s\n",
3323 frr_config
, safe_strerror(errno
));
3328 pwentry
= getpwnam(FRR_USER
);
3330 uid
= pwentry
->pw_uid
;
3332 printf("%% Warning: could not look up user \"%s\"\n", FRR_USER
);
3337 grentry
= getgrnam(FRR_GROUP
);
3339 gid
= grentry
->gr_gid
;
3341 printf("%% Warning: could not look up group \"%s\"\n",
3347 if (!fstat(fd
, &st
)) {
3348 if (st
.st_uid
== uid
)
3350 if (st
.st_gid
== gid
)
3352 if ((uid
!= (uid_t
)-1 || gid
!= (gid_t
)-1)
3353 && fchown(fd
, uid
, gid
)) {
3354 printf("%% Warning: can't chown configuration file %s: %s\n",
3355 frr_config
, safe_strerror(errno
));
3359 printf("%% Warning: stat() failed on %s: %s\n", frr_config
,
3360 safe_strerror(errno
));
3364 if (fflush(fp
) != 0) {
3365 printf("%% Warning: fflush() failed on %s: %s\n", frr_config
,
3366 safe_strerror(errno
));
3370 if (fsync(fd
) < 0) {
3371 printf("%% Warning: fsync() failed on %s: %s\n", frr_config
,
3372 safe_strerror(errno
));
3378 printf("Integrated configuration saved to %s\n", frr_config
);
3386 static bool want_config_integrated(void)
3390 switch (vtysh_write_integrated
) {
3391 case WRITE_INTEGRATED_UNSPECIFIED
:
3392 if (stat(frr_config
, &s
) && errno
== ENOENT
)
3395 case WRITE_INTEGRATED_NO
:
3397 case WRITE_INTEGRATED_YES
:
3403 DEFUN (vtysh_write_memory
,
3404 vtysh_write_memory_cmd
,
3405 "write [<memory|file>]",
3406 "Write running configuration to memory, network, or terminal\n"
3407 "Write configuration to the file (same as write file)\n"
3408 "Write configuration to the file (same as write memory)\n")
3410 int ret
= CMD_SUCCESS
;
3411 char line
[] = "do write memory";
3414 vty_out(vty
, "Note: this version of vtysh never writes vtysh.conf\n");
3416 /* If integrated frr.conf explicitly set. */
3417 if (want_config_integrated()) {
3418 ret
= CMD_WARNING_CONFIG_FAILED
;
3420 /* first attempt to use watchfrr if it's available */
3421 bool used_watchfrr
= false;
3423 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3424 if (vtysh_client
[i
].flag
== VTYSH_WATCHFRR
)
3426 if (i
< array_size(vtysh_client
) && vtysh_client
[i
].fd
!= -1) {
3427 used_watchfrr
= true;
3428 ret
= vtysh_client_execute(&vtysh_client
[i
],
3429 "do write integrated");
3433 * If we didn't use watchfrr, fallback to writing the config
3436 if (!used_watchfrr
) {
3437 printf("\nWarning: attempting direct configuration write without watchfrr.\nFile permissions and ownership may be incorrect, or write may fail.\n\n");
3438 ret
= vtysh_write_config_integrated();
3443 vty_out(vty
, "Building Configuration...\n");
3445 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3446 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3451 DEFUN (vtysh_copy_running_config
,
3452 vtysh_copy_running_config_cmd
,
3453 "copy running-config startup-config",
3454 "Copy from one file to another\n"
3455 "Copy from current system configuration\n"
3456 "Copy to startup configuration\n")
3458 return vtysh_write_memory(self
, vty
, argc
, argv
);
3461 DEFUN (vtysh_copy_to_running
,
3462 vtysh_copy_to_running_cmd
,
3463 "copy FILENAME running-config",
3464 "Apply a configuration file\n"
3465 "Configuration file to read\n"
3466 "Apply to current configuration\n")
3469 const char *fname
= argv
[1]->arg
;
3471 ret
= vtysh_read_config(fname
, true);
3473 /* Return to enable mode - the 'read_config' api leaves us up a level */
3474 vtysh_execute_no_pager("enable");
3479 DEFUN (vtysh_terminal_paginate
,
3480 vtysh_terminal_paginate_cmd
,
3481 "[no] terminal paginate",
3483 "Set terminal line parameters\n"
3484 "Use pager for output scrolling\n")
3486 free(vtysh_pager_name
);
3487 vtysh_pager_name
= NULL
;
3489 if (strcmp(argv
[0]->text
, "no"))
3490 vtysh_pager_envdef(true);
3494 DEFUN (vtysh_terminal_length
,
3495 vtysh_terminal_length_cmd
,
3496 "[no] terminal length (0-4294967295)",
3498 "Set terminal line parameters\n"
3499 "Set number of lines on a screen\n"
3500 "Number of lines on screen (0 for no pausing, nonzero to use pager)\n")
3503 unsigned long lines
;
3505 free(vtysh_pager_name
);
3506 vtysh_pager_name
= NULL
;
3508 if (!strcmp(argv
[0]->text
, "no") || !strcmp(argv
[1]->text
, "no")) {
3509 /* "terminal no length" = use VTYSH_PAGER */
3510 vtysh_pager_envdef(true);
3514 lines
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
3517 "%% The \"terminal length\" command is deprecated and its value is ignored.\n"
3518 "%% Please use \"terminal paginate\" instead with OS TTY length handling.\n");
3519 vtysh_pager_envdef(true);
3525 ALIAS_DEPRECATED(vtysh_terminal_length
,
3526 vtysh_terminal_no_length_cmd
,
3527 "terminal no length",
3528 "Set terminal line parameters\n"
3530 "Set number of lines on a screen\n")
3532 DEFUN (vtysh_show_daemons
,
3533 vtysh_show_daemons_cmd
,
3536 "Show list of running daemons\n")
3540 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3541 if (vtysh_client
[i
].fd
>= 0)
3542 vty_out(vty
, " %s", vtysh_client
[i
].name
);
3548 struct visual_prio
{
3549 /* 4 characters for nice alignment */
3552 int c256_background
;
3556 /* clang-format off */
3557 struct visual_prio visual_prios
[] = {
3559 .label
= "\e[31;1mEMRG",
3560 .c256_background
= 53,
3561 .c256_formatarg
= 225,
3564 .label
= "\e[31;1mALRT",
3565 .c256_background
= 53,
3566 .c256_formatarg
= 225,
3569 .label
= "\e[31;1mCRIT",
3570 .c256_background
= 53,
3571 .c256_formatarg
= 225,
3574 .label
= "\e[38;5;202mERR!",
3575 .c256_background
= 52,
3576 .c256_formatarg
= 224,
3579 .label
= "\e[38;5;222mWARN",
3580 .c256_background
= 58,
3581 .c256_formatarg
= 230,
3585 .c256_background
= 234,
3586 .c256_formatarg
= 195,
3589 .label
= "\e[38;5;192mINFO",
3590 .c256_background
= 236,
3591 .c256_formatarg
= 195,
3594 .label
= "\e[38;5;116mDEBG",
3595 .c256_background
= 238,
3596 .c256_formatarg
= 195,
3599 /* clang-format on */
3601 static void vtysh_log_print(struct vtysh_client
*vclient
,
3602 struct zlog_live_hdr
*hdr
, const char *text
)
3604 size_t textlen
= hdr
->textlen
, textpos
= 0;
3605 time_t ts
= hdr
->ts_sec
;
3606 struct visual_prio
*vis
;
3610 if (hdr
->prio
>= array_size(visual_prios
))
3611 vis
= &visual_prios
[LOG_CRIT
];
3613 vis
= &visual_prios
[hdr
->prio
];
3615 localtime_r(&ts
, &tm
);
3616 strftime(ts_buf
, sizeof(ts_buf
), "%Y-%m-%d %H:%M:%S", &tm
);
3619 const char *label
= vis
->label
+ strlen(vis
->label
) - 4;
3621 fprintf(stderr
, "%s.%03u [%s] %s: %.*s\n", ts_buf
,
3622 hdr
->ts_nsec
/ 1000000U, label
, vclient
->name
,
3623 (int)textlen
, text
);
3628 "\e[48;5;%dm\e[38;5;247m%s.%03u [%s\e[38;5;247m] \e[38;5;255m%s\e[38;5;247m: \e[38;5;251m",
3629 vis
->c256_background
, ts_buf
, hdr
->ts_nsec
/ 1000000U,
3630 vis
->label
, vclient
->name
);
3632 for (size_t fmtpos
= 0; fmtpos
< hdr
->n_argpos
; fmtpos
++) {
3633 struct fmt_outpos
*fmt
= &hdr
->argpos
[fmtpos
];
3635 if (fmt
->off_start
< textpos
|| fmt
->off_end
< fmt
->off_start
||
3636 fmt
->off_end
> textlen
)
3639 while (fmt
->off_end
> fmt
->off_start
&&
3640 text
[fmt
->off_end
- 1] == ' ')
3643 fprintf(stderr
, "%.*s\e[38;5;%dm%.*s\e[38;5;251m",
3644 (int)(fmt
->off_start
- textpos
), text
+ textpos
,
3645 vis
->c256_formatarg
,
3646 (int)(fmt
->off_end
- fmt
->off_start
),
3647 text
+ fmt
->off_start
);
3648 textpos
= fmt
->off_end
;
3650 fprintf(stderr
, "%.*s\033[K\033[m\n", (int)(textlen
- textpos
),
3654 static void vtysh_log_read(struct thread
*thread
)
3656 struct vtysh_client
*vclient
= THREAD_ARG(thread
);
3658 struct zlog_live_hdr hdr
;
3664 thread_add_read(master
, vtysh_log_read
, vclient
, vclient
->log_fd
,
3665 &vclient
->log_reader
);
3667 ret
= recv(vclient
->log_fd
, &buf
, sizeof(buf
), 0);
3669 if (ret
< 0 && ERRNO_IO_RETRY(errno
))
3672 if (stderr_stdout_same
) {
3673 #ifdef HAVE_RL_CLEAR_VISIBLE_LINE
3674 rl_clear_visible_line();
3684 buf
.text
[0] = '\0'; /* coverity */
3687 snprintfrr(buf
.text
, sizeof(buf
.text
),
3688 "log monitor connection error: %m");
3691 buf
.text
, sizeof(buf
.text
),
3692 "log monitor connection closed unexpectedly");
3693 buf
.hdr
.textlen
= strlen(buf
.text
);
3695 THREAD_OFF(vclient
->log_reader
);
3696 close(vclient
->log_fd
);
3697 vclient
->log_fd
= -1;
3699 clock_gettime(CLOCK_REALTIME
, &ts
);
3700 buf
.hdr
.ts_sec
= ts
.tv_sec
;
3701 buf
.hdr
.ts_nsec
= ts
.tv_nsec
;
3702 buf
.hdr
.prio
= LOG_ERR
;
3704 buf
.hdr
.texthdrlen
= 0;
3705 buf
.hdr
.n_argpos
= 0;
3707 int32_t lost_msgs
= buf
.hdr
.lost_msgs
- vclient
->lost_msgs
;
3709 if (lost_msgs
> 0) {
3710 vclient
->lost_msgs
= buf
.hdr
.lost_msgs
;
3712 "%d log messages from %s lost (vtysh reading too slowly)\n",
3713 lost_msgs
, vclient
->name
);
3717 text
= buf
.text
+ sizeof(buf
.hdr
.argpos
[0]) * buf
.hdr
.n_argpos
;
3718 vtysh_log_print(vclient
, &buf
.hdr
, text
);
3720 if (stderr_stdout_same
)
3721 rl_forced_update_display();
3727 /* clippy/clidef can't process the DEFPY below without some value for this */
3728 #define DAEMONS_LIST "daemon"
3731 DEFPY (vtysh_terminal_monitor
,
3732 vtysh_terminal_monitor_cmd
,
3733 "terminal monitor ["DAEMONS_LIST
"]$daemon",
3734 "Set terminal line parameters\n"
3735 "Receive log messages to active VTY session\n"
3738 static const char line
[] = "terminal monitor";
3739 int ret_all
= CMD_SUCCESS
, ret
, fd
;
3742 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3743 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3745 if (daemon
&& strcmp(vclient
->name
, daemon
))
3748 for (; vclient
; vclient
= vclient
->next
) {
3749 if (vclient
->log_fd
!= -1) {
3750 vty_out(vty
, "%% %s: already monitoring logs\n",
3757 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, &fd
);
3759 set_nonblocking(fd
);
3760 vclient
->log_fd
= fd
;
3761 thread_add_read(master
, vtysh_log_read
, vclient
,
3763 &vclient
->log_reader
);
3765 if (ret
!= CMD_SUCCESS
) {
3766 vty_out(vty
, "%% failed to enable logs on %s\n",
3768 ret_all
= CMD_WARNING
;
3774 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3776 "%% command had no effect, relevant daemons not connected?\n");
3777 ret_all
= CMD_WARNING
;
3782 DEFPY (no_vtysh_terminal_monitor
,
3783 no_vtysh_terminal_monitor_cmd
,
3784 "no terminal monitor ["DAEMONS_LIST
"]$daemon",
3786 "Set terminal line parameters\n"
3787 "Receive log messages to active VTY session\n"
3790 static const char line
[] = "no terminal monitor";
3791 int ret_all
= CMD_SUCCESS
, ret
;
3794 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3795 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3797 if (daemon
&& strcmp(vclient
->name
, daemon
))
3800 for (; vclient
; vclient
= vclient
->next
) {
3801 /* run this even if log_fd == -1, in case something
3804 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, NULL
);
3805 if (ret
!= CMD_SUCCESS
) {
3807 "%% failed to disable logs on %s\n",
3809 ret_all
= CMD_WARNING
;
3813 /* with this being a datagram socket, we can't expect
3814 * a close notification...
3816 if (vclient
->log_fd
!= -1) {
3817 THREAD_OFF(vclient
->log_reader
);
3819 close(vclient
->log_fd
);
3820 vclient
->log_fd
= -1;
3825 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3827 "%% command had no effect, relevant daemons not connected?\n");
3828 ret_all
= CMD_WARNING
;
3834 /* Execute command in child process. */
3835 static void execute_command(const char *command
, int argc
, const char *arg1
,
3845 /* Failure of fork(). */
3846 fprintf(stderr
, "Can't fork: %s\n", safe_strerror(errno
));
3848 } else if (pid
== 0) {
3849 /* This is child process. */
3852 execlp(command
, command
, (const char *)NULL
);
3855 execlp(command
, command
, arg1
, (const char *)NULL
);
3858 execlp(command
, command
, arg1
, arg2
,
3859 (const char *)NULL
);
3863 /* When execlp suceed, this part is not executed. */
3864 fprintf(stderr
, "Can't execute %s: %s\n", command
,
3865 safe_strerror(errno
));
3868 /* This is parent. */
3870 wait4(pid
, &status
, 0, NULL
);
3878 "Send echo messages\n"
3879 "Ping destination address or hostname\n")
3883 argv_find(argv
, argc
, "WORD", &idx
);
3884 execute_command("ping", 1, argv
[idx
]->arg
, NULL
);
3888 ALIAS(vtysh_ping
, vtysh_ping_ip_cmd
, "ping ip WORD",
3889 "Send echo messages\n"
3891 "Ping destination address or hostname\n")
3893 DEFUN (vtysh_traceroute
,
3894 vtysh_traceroute_cmd
,
3896 "Trace route to destination\n"
3897 "Trace route to destination address or hostname\n")
3901 argv_find(argv
, argc
, "WORD", &idx
);
3902 execute_command("traceroute", 1, argv
[idx
]->arg
, NULL
);
3906 ALIAS(vtysh_traceroute
, vtysh_traceroute_ip_cmd
, "traceroute ip WORD",
3907 "Trace route to destination\n"
3909 "Trace route to destination address or hostname\n")
3911 DEFUN (vtysh_mtrace
,
3913 "mtrace WORD [WORD]",
3914 "Multicast trace route to multicast source\n"
3915 "Multicast trace route to multicast source address\n"
3916 "Multicast trace route for multicast group address\n")
3919 execute_command("mtracebis", 1, argv
[1]->arg
, NULL
);
3921 execute_command("mtracebis", 2, argv
[1]->arg
, argv
[2]->arg
);
3928 "Send echo messages\n"
3930 "Ping destination address or hostname\n")
3932 execute_command("ping6", 1, argv
[2]->arg
, NULL
);
3936 DEFUN (vtysh_traceroute6
,
3937 vtysh_traceroute6_cmd
,
3938 "traceroute ipv6 WORD",
3939 "Trace route to destination\n"
3941 "Trace route to destination address or hostname\n")
3943 execute_command("traceroute6", 1, argv
[2]->arg
, NULL
);
3947 #if defined(HAVE_SHELL_ACCESS)
3948 DEFUN (vtysh_telnet
,
3951 "Open a telnet connection\n"
3952 "IP address or hostname of a remote system\n")
3954 execute_command("telnet", 1, argv
[1]->arg
, NULL
);
3958 DEFUN (vtysh_telnet_port
,
3959 vtysh_telnet_port_cmd
,
3961 "Open a telnet connection\n"
3962 "IP address or hostname of a remote system\n"
3963 "TCP Port number\n")
3965 execute_command("telnet", 2, argv
[1]->arg
, argv
[2]->arg
);
3972 "Open an ssh connection\n"
3975 execute_command("ssh", 1, argv
[1]->arg
, NULL
);
3979 DEFUN (vtysh_start_shell
,
3980 vtysh_start_shell_cmd
,
3982 "Start UNIX shell\n")
3984 execute_command("sh", 0, NULL
, NULL
);
3988 DEFUN (vtysh_start_bash
,
3989 vtysh_start_bash_cmd
,
3991 "Start UNIX shell\n"
3994 execute_command("bash", 0, NULL
, NULL
);
3998 DEFUN (vtysh_start_zsh
,
3999 vtysh_start_zsh_cmd
,
4001 "Start UNIX shell\n"
4004 execute_command("zsh", 0, NULL
, NULL
);
4011 "list [permutations]",
4012 "Print command list\n"
4013 "Print all possible command permutations\n")
4015 return cmd_list_cmds(vty
, argc
== 2);
4018 DEFUN (vtysh_output_file
,
4019 vtysh_output_file_cmd
,
4021 "Direct vtysh output to file\n"
4022 "Direct vtysh output to file\n"
4023 "Path to dump output to\n")
4025 const char *path
= argv
[argc
- 1]->arg
;
4026 vty
->of
= fopen(path
, "a");
4028 vty_out(vty
, "Failed to open file '%s': %s\n", path
,
4029 safe_strerror(errno
));
4035 DEFUN (no_vtysh_output_file
,
4036 no_vtysh_output_file_cmd
,
4037 "no output file [FILE]",
4039 "Direct vtysh output to file\n"
4040 "Direct vtysh output to file\n"
4041 "Path to dump output to\n")
4043 if (vty
->of
!= stdout
) {
4053 "Find CLI command matching a regular expression\n"
4054 "Search pattern (POSIX regex)\n")
4056 return cmd_find_cmds(vty
, argv
, argc
);
4059 DEFUN_HIDDEN(show_cli_graph_vtysh
,
4060 show_cli_graph_vtysh_cmd
,
4064 "Dump current command space as DOT graph\n")
4066 struct cmd_node
*cn
= vector_slot(cmdvec
, vty
->node
);
4067 char *dot
= cmd_graph_dump_dot(cn
->cmdgraph
);
4069 vty_out(vty
, "%s\n", dot
);
4070 XFREE(MTYPE_TMP
, dot
);
4074 static void vtysh_install_default(enum node_type node
)
4076 _install_element(node
, &config_list_cmd
);
4077 _install_element(node
, &find_cmd
);
4078 _install_element(node
, &show_cli_graph_vtysh_cmd
);
4079 _install_element(node
, &vtysh_output_file_cmd
);
4080 _install_element(node
, &no_vtysh_output_file_cmd
);
4083 /* Making connection to protocol daemon. */
4084 static int vtysh_connect(struct vtysh_client
*vclient
)
4088 struct sockaddr_un addr
;
4092 if (!vclient
->path
[0])
4093 snprintf(vclient
->path
, sizeof(vclient
->path
), "%s/%s.vty",
4094 vtydir
, vclient
->name
);
4095 path
= vclient
->path
;
4097 /* Stat socket to see if we have permission to access it. */
4098 ret
= stat(path
, &s_stat
);
4099 if (ret
< 0 && errno
!= ENOENT
) {
4100 fprintf(stderr
, "vtysh_connect(%s): stat = %s\n", path
,
4101 safe_strerror(errno
));
4106 if (!S_ISSOCK(s_stat
.st_mode
)) {
4107 fprintf(stderr
, "vtysh_connect(%s): Not a socket\n",
4113 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
4116 fprintf(stderr
, "vtysh_connect(%s): socket = %s\n", path
,
4117 safe_strerror(errno
));
4122 memset(&addr
, 0, sizeof(addr
));
4123 addr
.sun_family
= AF_UNIX
;
4124 strlcpy(addr
.sun_path
, path
, sizeof(addr
.sun_path
));
4125 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
4126 len
= addr
.sun_len
= SUN_LEN(&addr
);
4128 len
= sizeof(addr
.sun_family
) + strlen(addr
.sun_path
);
4129 #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
4131 ret
= connect(sock
, (struct sockaddr
*)&addr
, len
);
4134 fprintf(stderr
, "vtysh_connect(%s): connect = %s\n", path
,
4135 safe_strerror(errno
));
4145 static int vtysh_reconnect(struct vtysh_client
*vclient
)
4149 fprintf(stderr
, "Warning: connecting to %s...", vclient
->name
);
4150 ret
= vtysh_connect(vclient
);
4152 fprintf(stderr
, "failed!\n");
4155 fprintf(stderr
, "success!\n");
4156 if (vtysh_client_execute(vclient
, "enable") < 0)
4158 return vtysh_execute_no_pager("end");
4161 /* Return true if str ends with suffix, else return false */
4162 static int ends_with(const char *str
, const char *suffix
)
4164 if (!str
|| !suffix
)
4166 size_t lenstr
= strlen(str
);
4167 size_t lensuffix
= strlen(suffix
);
4168 if (lensuffix
> lenstr
)
4170 return strncmp(str
+ lenstr
- lensuffix
, suffix
, lensuffix
) == 0;
4173 static void vtysh_client_sorted_insert(struct vtysh_client
*head_client
,
4174 struct vtysh_client
*client
)
4176 struct vtysh_client
*prev_node
, *current_node
;
4178 prev_node
= head_client
;
4179 current_node
= head_client
->next
;
4180 while (current_node
) {
4181 if (strcmp(current_node
->path
, client
->path
) > 0)
4184 prev_node
= current_node
;
4185 current_node
= current_node
->next
;
4187 client
->next
= current_node
;
4188 prev_node
->next
= client
;
4191 #define MAXIMUM_INSTANCES 10
4193 static void vtysh_update_all_instances(struct vtysh_client
*head_client
)
4195 struct vtysh_client
*client
;
4197 struct dirent
*file
;
4200 if (head_client
->flag
!= VTYSH_OSPFD
)
4203 /* ls vty_sock_dir and look for all files ending in .vty */
4204 dir
= opendir(vtydir
);
4206 while ((file
= readdir(dir
)) != NULL
) {
4207 if (frrstr_startswith(file
->d_name
, "ospfd-")
4208 && ends_with(file
->d_name
, ".vty")) {
4209 if (n
== MAXIMUM_INSTANCES
) {
4211 "Parsing %s, client limit(%d) reached!\n",
4215 client
= (struct vtysh_client
*)malloc(
4216 sizeof(struct vtysh_client
));
4218 client
->name
= "ospfd";
4219 client
->flag
= VTYSH_OSPFD
;
4220 snprintf(client
->path
, sizeof(client
->path
),
4221 "%s/%s", vtydir
, file
->d_name
);
4222 client
->next
= NULL
;
4223 vtysh_client_sorted_insert(head_client
, client
);
4231 static int vtysh_connect_all_instances(struct vtysh_client
*head_client
)
4233 struct vtysh_client
*client
;
4236 vtysh_update_all_instances(head_client
);
4238 client
= head_client
->next
;
4240 if (vtysh_connect(client
) == 0)
4242 client
= client
->next
;
4248 int vtysh_connect_all(const char *daemon_name
)
4254 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
4256 || !strcmp(daemon_name
, vtysh_client
[i
].name
)) {
4258 if (vtysh_connect(&vtysh_client
[i
]) == 0)
4261 rc
+= vtysh_connect_all_instances(&vtysh_client
[i
]);
4265 fprintf(stderr
, "Error: no daemons match name %s!\n",
4270 /* To disable readline's filename completion. */
4271 static char *vtysh_completion_entry_function(const char *ignore
,
4277 void vtysh_readline_init(void)
4279 /* readline related settings. */
4280 char *disable_bracketed_paste
=
4281 XSTRDUP(MTYPE_TMP
, "set enable-bracketed-paste off");
4284 rl_parse_and_bind(disable_bracketed_paste
);
4285 rl_bind_key('?', (rl_command_func_t
*)vtysh_rl_describe
);
4286 rl_completion_entry_function
= vtysh_completion_entry_function
;
4287 rl_attempted_completion_function
= new_completion
;
4289 XFREE(MTYPE_TMP
, disable_bracketed_paste
);
4292 char *vtysh_prompt(void)
4294 static char buf
[512];
4296 snprintf(buf
, sizeof(buf
), cmd_prompt(vty
->node
), cmd_hostname_get());
4300 static void vtysh_ac_line(void *arg
, const char *line
)
4304 for (i
= 0; i
< vector_active(comps
); i
++)
4305 if (!strcmp(line
, (char *)vector_slot(comps
, i
)))
4307 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, line
));
4310 static void vtysh_autocomplete(vector comps
, struct cmd_token
*token
)
4315 snprintf(accmd
, sizeof(accmd
), "autocomplete %d %s %s", token
->type
,
4316 token
->text
, token
->varname
? token
->varname
: "-");
4318 vty
->of_saved
= vty
->of
;
4320 for (i
= 0; i
< array_size(vtysh_client
); i
++)
4321 vtysh_client_run_all(&vtysh_client
[i
], accmd
, 1, vtysh_ac_line
,
4323 vty
->of
= vty
->of_saved
;
4326 static const struct cmd_variable_handler vtysh_var_handler
[] = {
4330 .completions
= vtysh_autocomplete
},
4331 {.completions
= NULL
}};
4333 void vtysh_uninit(void)
4335 if (vty
->of
!= stdout
)
4339 void vtysh_init_vty(void)
4341 struct stat st_out
, st_err
;
4343 cmd_defer_tree(true);
4345 for (size_t i
= 0; i
< array_size(vtysh_client
); i
++) {
4346 vtysh_client
[i
].fd
= -1;
4347 vtysh_client
[i
].log_fd
= -1;
4350 stderr_tty
= isatty(STDERR_FILENO
);
4352 if (fstat(STDOUT_FILENO
, &st_out
) || fstat(STDERR_FILENO
, &st_err
) ||
4353 (st_out
.st_dev
== st_err
.st_dev
&& st_out
.st_ino
== st_err
.st_ino
))
4354 stderr_stdout_same
= true;
4356 /* Make vty structure. */
4358 vty
->type
= VTY_SHELL
;
4359 vty
->node
= VIEW_NODE
;
4361 /* set default output */
4363 vtysh_pager_envdef(false);
4365 /* Initialize commands. */
4367 cmd_variable_handler_register(vtysh_var_handler
);
4371 install_node(&bgp_node
);
4372 install_element(CONFIG_NODE
, &router_bgp_cmd
);
4373 install_element(BGP_NODE
, &vtysh_exit_bgpd_cmd
);
4374 install_element(BGP_NODE
, &vtysh_quit_bgpd_cmd
);
4375 install_element(BGP_NODE
, &vtysh_end_all_cmd
);
4377 install_node(&bgp_vpnv4_node
);
4378 install_element(BGP_NODE
, &address_family_ipv4_vpn_cmd
);
4379 #ifdef KEEP_OLD_VPN_COMMANDS
4380 install_element(BGP_NODE
, &address_family_vpnv4_cmd
);
4381 #endif /* KEEP_OLD_VPN_COMMANDS */
4382 install_element(BGP_VPNV4_NODE
, &vtysh_exit_bgpd_cmd
);
4383 install_element(BGP_VPNV4_NODE
, &vtysh_quit_bgpd_cmd
);
4384 install_element(BGP_VPNV4_NODE
, &vtysh_end_all_cmd
);
4385 install_element(BGP_VPNV4_NODE
, &exit_address_family_cmd
);
4387 install_node(&bgp_vpnv6_node
);
4388 install_element(BGP_NODE
, &address_family_ipv6_vpn_cmd
);
4389 #ifdef KEEP_OLD_VPN_COMMANDS
4390 install_element(BGP_NODE
, &address_family_vpnv6_cmd
);
4391 #endif /* KEEP_OLD_VPN_COMMANDS */
4392 install_element(BGP_VPNV6_NODE
, &vtysh_exit_bgpd_cmd
);
4393 install_element(BGP_VPNV6_NODE
, &vtysh_quit_bgpd_cmd
);
4394 install_element(BGP_VPNV6_NODE
, &vtysh_end_all_cmd
);
4395 install_element(BGP_VPNV6_NODE
, &exit_address_family_cmd
);
4397 install_node(&bgp_flowspecv4_node
);
4398 install_element(BGP_NODE
, &address_family_flowspecv4_cmd
);
4399 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_exit_bgpd_cmd
);
4400 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_quit_bgpd_cmd
);
4401 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_end_all_cmd
);
4402 install_element(BGP_FLOWSPECV4_NODE
, &exit_address_family_cmd
);
4404 install_node(&bgp_flowspecv6_node
);
4405 install_element(BGP_NODE
, &address_family_flowspecv6_cmd
);
4406 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_exit_bgpd_cmd
);
4407 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_quit_bgpd_cmd
);
4408 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_end_all_cmd
);
4409 install_element(BGP_FLOWSPECV6_NODE
, &exit_address_family_cmd
);
4411 install_node(&bgp_ipv4_node
);
4412 install_element(BGP_NODE
, &address_family_ipv4_cmd
);
4413 install_element(BGP_IPV4_NODE
, &vtysh_exit_bgpd_cmd
);
4414 install_element(BGP_IPV4_NODE
, &vtysh_quit_bgpd_cmd
);
4415 install_element(BGP_IPV4_NODE
, &vtysh_end_all_cmd
);
4416 install_element(BGP_IPV4_NODE
, &exit_address_family_cmd
);
4418 install_node(&bgp_ipv4m_node
);
4419 install_element(BGP_NODE
, &address_family_ipv4_multicast_cmd
);
4420 install_element(BGP_IPV4M_NODE
, &vtysh_exit_bgpd_cmd
);
4421 install_element(BGP_IPV4M_NODE
, &vtysh_quit_bgpd_cmd
);
4422 install_element(BGP_IPV4M_NODE
, &vtysh_end_all_cmd
);
4423 install_element(BGP_IPV4M_NODE
, &exit_address_family_cmd
);
4425 install_node(&bgp_ipv4l_node
);
4426 install_element(BGP_NODE
, &address_family_ipv4_labeled_unicast_cmd
);
4427 install_element(BGP_IPV4L_NODE
, &vtysh_exit_bgpd_cmd
);
4428 install_element(BGP_IPV4L_NODE
, &vtysh_quit_bgpd_cmd
);
4429 install_element(BGP_IPV4L_NODE
, &vtysh_end_all_cmd
);
4430 install_element(BGP_IPV4L_NODE
, &exit_address_family_cmd
);
4432 install_node(&bgp_ipv6_node
);
4433 install_element(BGP_NODE
, &address_family_ipv6_cmd
);
4434 install_element(BGP_IPV6_NODE
, &vtysh_exit_bgpd_cmd
);
4435 install_element(BGP_IPV6_NODE
, &vtysh_quit_bgpd_cmd
);
4436 install_element(BGP_IPV6_NODE
, &vtysh_end_all_cmd
);
4437 install_element(BGP_IPV6_NODE
, &exit_address_family_cmd
);
4439 install_node(&bgp_ipv6m_node
);
4440 install_element(BGP_NODE
, &address_family_ipv6_multicast_cmd
);
4441 install_element(BGP_IPV6M_NODE
, &vtysh_exit_bgpd_cmd
);
4442 install_element(BGP_IPV6M_NODE
, &vtysh_quit_bgpd_cmd
);
4443 install_element(BGP_IPV6M_NODE
, &vtysh_end_all_cmd
);
4444 install_element(BGP_IPV6M_NODE
, &exit_address_family_cmd
);
4446 install_node(&bgp_ipv6l_node
);
4447 install_element(BGP_NODE
, &address_family_ipv6_labeled_unicast_cmd
);
4448 install_element(BGP_IPV6L_NODE
, &vtysh_exit_bgpd_cmd
);
4449 install_element(BGP_IPV6L_NODE
, &vtysh_quit_bgpd_cmd
);
4450 install_element(BGP_IPV6L_NODE
, &vtysh_end_all_cmd
);
4451 install_element(BGP_IPV6L_NODE
, &exit_address_family_cmd
);
4453 #if defined(ENABLE_BGP_VNC)
4454 install_node(&bgp_vrf_policy_node
);
4455 install_element(BGP_NODE
, &vnc_vrf_policy_cmd
);
4456 install_element(BGP_VRF_POLICY_NODE
, &vtysh_exit_bgpd_cmd
);
4457 install_element(BGP_VRF_POLICY_NODE
, &vtysh_quit_bgpd_cmd
);
4458 install_element(BGP_VRF_POLICY_NODE
, &vtysh_end_all_cmd
);
4459 install_element(BGP_VRF_POLICY_NODE
, &exit_vrf_policy_cmd
);
4461 install_node(&bgp_vnc_defaults_node
);
4462 install_element(BGP_NODE
, &vnc_defaults_cmd
);
4463 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_exit_bgpd_cmd
);
4464 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_quit_bgpd_cmd
);
4465 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_end_all_cmd
);
4466 install_element(BGP_VNC_DEFAULTS_NODE
, &exit_vnc_config_cmd
);
4468 install_node(&bgp_vnc_nve_group_node
);
4469 install_element(BGP_NODE
, &vnc_nve_group_cmd
);
4470 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4471 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4472 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_end_all_cmd
);
4473 install_element(BGP_VNC_NVE_GROUP_NODE
, &exit_vnc_config_cmd
);
4475 install_node(&bgp_vnc_l2_group_node
);
4476 install_element(BGP_NODE
, &vnc_l2_group_cmd
);
4477 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4478 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4479 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_end_all_cmd
);
4480 install_element(BGP_VNC_L2_GROUP_NODE
, &exit_vnc_config_cmd
);
4483 install_node(&bgp_evpn_node
);
4484 install_element(BGP_NODE
, &address_family_evpn_cmd
);
4485 install_element(BGP_EVPN_NODE
, &vtysh_quit_bgpd_cmd
);
4486 install_element(BGP_EVPN_NODE
, &vtysh_exit_bgpd_cmd
);
4487 install_element(BGP_EVPN_NODE
, &vtysh_end_all_cmd
);
4488 install_element(BGP_EVPN_NODE
, &exit_address_family_cmd
);
4490 install_node(&bgp_evpn_vni_node
);
4491 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
4492 install_element(BGP_EVPN_VNI_NODE
, &vtysh_exit_bgpd_cmd
);
4493 install_element(BGP_EVPN_VNI_NODE
, &vtysh_quit_bgpd_cmd
);
4494 install_element(BGP_EVPN_VNI_NODE
, &vtysh_end_all_cmd
);
4495 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
4497 install_node(&rpki_node
);
4498 install_element(CONFIG_NODE
, &rpki_cmd
);
4499 install_element(RPKI_NODE
, &rpki_exit_cmd
);
4500 install_element(RPKI_NODE
, &rpki_quit_cmd
);
4501 install_element(RPKI_NODE
, &vtysh_end_all_cmd
);
4503 install_node(&bmp_node
);
4504 install_element(BGP_NODE
, &bmp_targets_cmd
);
4505 install_element(BMP_NODE
, &bmp_exit_cmd
);
4506 install_element(BMP_NODE
, &bmp_quit_cmd
);
4507 install_element(BMP_NODE
, &vtysh_end_all_cmd
);
4509 install_node(&bgp_srv6_node
);
4510 install_element(BGP_NODE
, &bgp_srv6_cmd
);
4511 install_element(BGP_SRV6_NODE
, &exit_bgp_srv6_cmd
);
4512 install_element(BGP_SRV6_NODE
, &quit_bgp_srv6_cmd
);
4513 install_element(BGP_SRV6_NODE
, &vtysh_end_all_cmd
);
4514 #endif /* HAVE_BGPD */
4517 install_node(&rip_node
);
4519 install_element(CONFIG_NODE
, &router_rip_cmd
);
4520 install_element(RIP_NODE
, &vtysh_exit_ripd_cmd
);
4521 install_element(RIP_NODE
, &vtysh_quit_ripd_cmd
);
4522 install_element(RIP_NODE
, &vtysh_end_all_cmd
);
4523 #endif /* HAVE_RIPD */
4526 install_node(&ripng_node
);
4528 install_element(CONFIG_NODE
, &router_ripng_cmd
);
4529 install_element(RIPNG_NODE
, &vtysh_exit_ripngd_cmd
);
4530 install_element(RIPNG_NODE
, &vtysh_quit_ripngd_cmd
);
4531 install_element(RIPNG_NODE
, &vtysh_end_all_cmd
);
4532 #endif /* HAVE_RIPNGD */
4536 install_node(&ospf_node
);
4537 install_element(CONFIG_NODE
, &router_ospf_cmd
);
4538 install_element(OSPF_NODE
, &vtysh_exit_ospfd_cmd
);
4539 install_element(OSPF_NODE
, &vtysh_quit_ospfd_cmd
);
4540 install_element(OSPF_NODE
, &vtysh_end_all_cmd
);
4541 #endif /* HAVE_OSPFD */
4545 install_node(&ospf6_node
);
4546 install_element(CONFIG_NODE
, &router_ospf6_cmd
);
4547 install_element(OSPF6_NODE
, &vtysh_exit_ospf6d_cmd
);
4548 install_element(OSPF6_NODE
, &vtysh_quit_ospf6d_cmd
);
4549 install_element(OSPF6_NODE
, &vtysh_end_all_cmd
);
4550 #endif /* HAVE_OSPF6D */
4553 #if defined(HAVE_LDPD)
4554 install_node(&ldp_node
);
4555 install_element(CONFIG_NODE
, &ldp_mpls_ldp_cmd
);
4556 install_element(LDP_NODE
, &vtysh_exit_ldpd_cmd
);
4557 install_element(LDP_NODE
, &vtysh_quit_ldpd_cmd
);
4558 install_element(LDP_NODE
, &vtysh_end_all_cmd
);
4560 install_node(&ldp_ipv4_node
);
4561 install_element(LDP_NODE
, &ldp_address_family_ipv4_cmd
);
4562 install_element(LDP_IPV4_NODE
, &vtysh_exit_ldpd_cmd
);
4563 install_element(LDP_IPV4_NODE
, &vtysh_quit_ldpd_cmd
);
4564 install_element(LDP_IPV4_NODE
, &ldp_exit_address_family_cmd
);
4565 install_element(LDP_IPV4_NODE
, &vtysh_end_all_cmd
);
4567 install_node(&ldp_ipv6_node
);
4568 install_element(LDP_NODE
, &ldp_address_family_ipv6_cmd
);
4569 install_element(LDP_IPV6_NODE
, &vtysh_exit_ldpd_cmd
);
4570 install_element(LDP_IPV6_NODE
, &vtysh_quit_ldpd_cmd
);
4571 install_element(LDP_IPV6_NODE
, &ldp_exit_address_family_cmd
);
4572 install_element(LDP_IPV6_NODE
, &vtysh_end_all_cmd
);
4574 install_node(&ldp_ipv4_iface_node
);
4575 install_element(LDP_IPV4_NODE
, &ldp_interface_ifname_cmd
);
4576 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4577 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4578 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_end_all_cmd
);
4580 install_node(&ldp_ipv6_iface_node
);
4581 install_element(LDP_IPV6_NODE
, &ldp_interface_ifname_cmd
);
4582 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4583 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4584 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_end_all_cmd
);
4586 install_node(&ldp_l2vpn_node
);
4587 install_element(CONFIG_NODE
, &ldp_l2vpn_word_type_vpls_cmd
);
4588 install_element(LDP_L2VPN_NODE
, &vtysh_exit_ldpd_cmd
);
4589 install_element(LDP_L2VPN_NODE
, &vtysh_quit_ldpd_cmd
);
4590 install_element(LDP_L2VPN_NODE
, &vtysh_end_all_cmd
);
4592 install_node(&ldp_pseudowire_node
);
4593 install_element(LDP_L2VPN_NODE
, &ldp_member_pseudowire_ifname_cmd
);
4594 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_exit_ldpd_cmd
);
4595 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_quit_ldpd_cmd
);
4596 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_end_all_cmd
);
4601 install_node(&eigrp_node
);
4602 install_element(CONFIG_NODE
, &router_eigrp_cmd
);
4603 install_element(EIGRP_NODE
, &vtysh_exit_eigrpd_cmd
);
4604 install_element(EIGRP_NODE
, &vtysh_quit_eigrpd_cmd
);
4605 install_element(EIGRP_NODE
, &vtysh_end_all_cmd
);
4606 #endif /* HAVE_EIGRPD */
4610 install_node(&babel_node
);
4611 install_element(CONFIG_NODE
, &router_babel_cmd
);
4612 install_element(BABEL_NODE
, &vtysh_exit_babeld_cmd
);
4613 install_element(BABEL_NODE
, &vtysh_quit_babeld_cmd
);
4614 install_element(BABEL_NODE
, &vtysh_end_all_cmd
);
4615 #endif /* HAVE_BABELD */
4619 install_node(&isis_node
);
4620 install_element(CONFIG_NODE
, &router_isis_cmd
);
4621 install_element(ISIS_NODE
, &vtysh_exit_isisd_cmd
);
4622 install_element(ISIS_NODE
, &vtysh_quit_isisd_cmd
);
4623 install_element(ISIS_NODE
, &vtysh_end_all_cmd
);
4624 #endif /* HAVE_ISISD */
4628 install_node(&openfabric_node
);
4629 install_element(CONFIG_NODE
, &router_openfabric_cmd
);
4630 install_element(OPENFABRIC_NODE
, &vtysh_exit_fabricd_cmd
);
4631 install_element(OPENFABRIC_NODE
, &vtysh_quit_fabricd_cmd
);
4632 install_element(OPENFABRIC_NODE
, &vtysh_end_all_cmd
);
4633 #endif /* HAVE_FABRICD */
4637 install_node(&pbr_map_node
);
4638 install_element(CONFIG_NODE
, &vtysh_pbr_map_cmd
);
4639 install_element(CONFIG_NODE
, &vtysh_no_pbr_map_cmd
);
4640 install_element(PBRMAP_NODE
, &vtysh_exit_pbr_map_cmd
);
4641 install_element(PBRMAP_NODE
, &vtysh_quit_pbr_map_cmd
);
4642 install_element(PBRMAP_NODE
, &vtysh_end_all_cmd
);
4643 #endif /* HAVE_PBRD */
4647 install_node(&bfd_node
);
4648 install_element(CONFIG_NODE
, &bfd_enter_cmd
);
4649 install_element(BFD_NODE
, &vtysh_exit_bfdd_cmd
);
4650 install_element(BFD_NODE
, &vtysh_quit_bfdd_cmd
);
4651 install_element(BFD_NODE
, &vtysh_end_all_cmd
);
4653 install_node(&bfd_peer_node
);
4654 install_element(BFD_NODE
, &bfd_peer_enter_cmd
);
4655 install_element(BFD_PEER_NODE
, &vtysh_exit_bfdd_cmd
);
4656 install_element(BFD_PEER_NODE
, &vtysh_quit_bfdd_cmd
);
4657 install_element(BFD_PEER_NODE
, &vtysh_end_all_cmd
);
4659 install_node(&bfd_profile_node
);
4660 install_element(BFD_NODE
, &bfd_profile_enter_cmd
);
4661 install_element(BFD_PROFILE_NODE
, &vtysh_exit_bfdd_cmd
);
4662 install_element(BFD_PROFILE_NODE
, &vtysh_quit_bfdd_cmd
);
4663 install_element(BFD_PROFILE_NODE
, &vtysh_end_all_cmd
);
4664 #endif /* HAVE_BFDD */
4666 install_node(&segment_routing_node
);
4667 install_element(CONFIG_NODE
, &segment_routing_cmd
);
4668 install_element(SEGMENT_ROUTING_NODE
, &vtysh_exit_sr_cmd
);
4669 install_element(SEGMENT_ROUTING_NODE
, &vtysh_quit_sr_cmd
);
4670 install_element(SEGMENT_ROUTING_NODE
, &vtysh_end_all_cmd
);
4672 #if defined(HAVE_PATHD)
4673 install_node(&sr_traffic_eng_node
);
4674 install_node(&srte_segment_list_node
);
4675 install_node(&srte_policy_node
);
4676 install_node(&srte_candidate_dyn_node
);
4678 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_exit_pathd_cmd
);
4679 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_quit_pathd_cmd
);
4680 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_exit_pathd_cmd
);
4681 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_quit_pathd_cmd
);
4682 install_element(SR_POLICY_NODE
, &vtysh_exit_pathd_cmd
);
4683 install_element(SR_POLICY_NODE
, &vtysh_quit_pathd_cmd
);
4684 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_exit_pathd_cmd
);
4685 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_quit_pathd_cmd
);
4688 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_end_all_cmd
);
4689 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_end_all_cmd
);
4690 install_element(SR_POLICY_NODE
, &vtysh_end_all_cmd
);
4691 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_end_all_cmd
);
4693 install_element(SEGMENT_ROUTING_NODE
, &sr_traffic_eng_cmd
);
4694 install_element(SR_TRAFFIC_ENG_NODE
, &srte_segment_list_cmd
);
4695 install_element(SR_TRAFFIC_ENG_NODE
, &srte_policy_cmd
);
4696 install_element(SR_POLICY_NODE
, &srte_policy_candidate_dyn_path_cmd
);
4698 install_node(&pcep_node
);
4699 install_node(&pcep_pcc_node
);
4700 install_node(&pcep_pce_node
);
4701 install_node(&pcep_pce_config_node
);
4703 install_element(PCEP_NODE
, &vtysh_exit_pathd_cmd
);
4704 install_element(PCEP_NODE
, &vtysh_quit_pathd_cmd
);
4705 install_element(PCEP_PCC_NODE
, &vtysh_exit_pathd_cmd
);
4706 install_element(PCEP_PCC_NODE
, &vtysh_quit_pathd_cmd
);
4707 install_element(PCEP_PCE_NODE
, &vtysh_exit_pathd_cmd
);
4708 install_element(PCEP_PCE_NODE
, &vtysh_quit_pathd_cmd
);
4709 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_exit_pathd_cmd
);
4710 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_quit_pathd_cmd
);
4712 install_element(PCEP_NODE
, &vtysh_end_all_cmd
);
4713 install_element(PCEP_PCC_NODE
, &vtysh_end_all_cmd
);
4714 install_element(PCEP_PCE_NODE
, &vtysh_end_all_cmd
);
4715 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_end_all_cmd
);
4717 install_element(SR_TRAFFIC_ENG_NODE
, &pcep_cmd
);
4718 install_element(PCEP_NODE
, &pcep_cli_pcc_cmd
);
4719 install_element(PCEP_NODE
, &pcep_cli_pcep_pce_config_cmd
);
4720 install_element(PCEP_NODE
, &pcep_cli_pce_cmd
);
4722 #endif /* HAVE_PATHD */
4725 install_node(&keychain_node
);
4726 install_element(CONFIG_NODE
, &key_chain_cmd
);
4727 install_element(KEYCHAIN_NODE
, &key_chain_cmd
);
4728 install_element(KEYCHAIN_NODE
, &vtysh_exit_keys_cmd
);
4729 install_element(KEYCHAIN_NODE
, &vtysh_quit_keys_cmd
);
4730 install_element(KEYCHAIN_NODE
, &vtysh_end_all_cmd
);
4732 install_node(&keychain_key_node
);
4733 install_element(KEYCHAIN_NODE
, &key_cmd
);
4734 install_element(KEYCHAIN_KEY_NODE
, &key_chain_cmd
);
4735 install_element(KEYCHAIN_KEY_NODE
, &vtysh_exit_keys_cmd
);
4736 install_element(KEYCHAIN_KEY_NODE
, &vtysh_quit_keys_cmd
);
4737 install_element(KEYCHAIN_KEY_NODE
, &vtysh_end_all_cmd
);
4740 install_node(&nh_group_node
);
4741 install_element(CONFIG_NODE
, &vtysh_nexthop_group_cmd
);
4742 install_element(CONFIG_NODE
, &vtysh_no_nexthop_group_cmd
);
4743 install_element(NH_GROUP_NODE
, &vtysh_end_all_cmd
);
4744 install_element(NH_GROUP_NODE
, &vtysh_exit_nexthop_group_cmd
);
4745 install_element(NH_GROUP_NODE
, &vtysh_quit_nexthop_group_cmd
);
4748 install_node(&zebra_node
);
4750 install_node(&interface_node
);
4751 install_element(CONFIG_NODE
, &vtysh_interface_cmd
);
4752 install_element(INTERFACE_NODE
, &vtysh_end_all_cmd
);
4753 install_element(INTERFACE_NODE
, &vtysh_exit_interface_cmd
);
4754 install_element(INTERFACE_NODE
, &vtysh_quit_interface_cmd
);
4756 install_node(&link_params_node
);
4757 install_element(INTERFACE_NODE
, &vtysh_link_params_cmd
);
4758 install_element(LINK_PARAMS_NODE
, &exit_link_params_cmd
);
4759 install_element(LINK_PARAMS_NODE
, &vtysh_end_all_cmd
);
4760 install_element(LINK_PARAMS_NODE
, &vtysh_exit_link_params_cmd
);
4761 install_element(LINK_PARAMS_NODE
, &vtysh_quit_link_params_cmd
);
4763 install_node(&pw_node
);
4764 install_element(CONFIG_NODE
, &vtysh_pseudowire_cmd
);
4765 install_element(PW_NODE
, &vtysh_end_all_cmd
);
4766 install_element(PW_NODE
, &vtysh_exit_pseudowire_cmd
);
4767 install_element(PW_NODE
, &vtysh_quit_pseudowire_cmd
);
4769 install_node(&vrf_node
);
4770 install_element(CONFIG_NODE
, &vtysh_vrf_cmd
);
4771 install_element(VRF_NODE
, &exit_vrf_config_cmd
);
4772 install_element(VRF_NODE
, &vtysh_end_all_cmd
);
4773 install_element(VRF_NODE
, &vtysh_exit_vrf_cmd
);
4774 install_element(VRF_NODE
, &vtysh_quit_vrf_cmd
);
4776 install_node(&rmap_node
);
4777 install_element(CONFIG_NODE
, &vtysh_route_map_cmd
);
4778 install_element(RMAP_NODE
, &vtysh_exit_rmap_cmd
);
4779 install_element(RMAP_NODE
, &vtysh_quit_rmap_cmd
);
4780 install_element(RMAP_NODE
, &vtysh_end_all_cmd
);
4782 install_node(&vty_node
);
4783 install_element(CONFIG_NODE
, &vtysh_line_vty_cmd
);
4784 install_element(VTY_NODE
, &vtysh_exit_line_vty_cmd
);
4785 install_element(VTY_NODE
, &vtysh_quit_line_vty_cmd
);
4786 install_element(VTY_NODE
, &vtysh_end_all_cmd
);
4789 struct cmd_node
*node
;
4790 for (unsigned int i
= 0; i
< vector_active(cmdvec
); i
++) {
4791 node
= vector_slot(cmdvec
, i
);
4792 if (!node
|| node
->node
== VIEW_NODE
)
4794 vtysh_install_default(node
->node
);
4800 install_element(VIEW_NODE
, &vtysh_enable_cmd
);
4801 install_element(ENABLE_NODE
, &vtysh_config_terminal_cmd
);
4802 install_element(ENABLE_NODE
, &vtysh_disable_cmd
);
4804 /* "exit" command. */
4805 install_element(VIEW_NODE
, &vtysh_exit_all_cmd
);
4806 install_element(CONFIG_NODE
, &vtysh_exit_all_cmd
);
4807 install_element(VIEW_NODE
, &vtysh_quit_all_cmd
);
4808 install_element(CONFIG_NODE
, &vtysh_quit_all_cmd
);
4810 /* "end" command. */
4811 install_element(CONFIG_NODE
, &vtysh_end_all_cmd
);
4812 install_element(ENABLE_NODE
, &vtysh_end_all_cmd
);
4814 /* SRv6 Data-plane */
4815 install_node(&srv6_node
);
4816 install_element(SEGMENT_ROUTING_NODE
, &srv6_cmd
);
4817 install_element(SRV6_NODE
, &srv6_locators_cmd
);
4818 install_element(SRV6_NODE
, &exit_srv6_config_cmd
);
4819 install_element(SRV6_NODE
, &vtysh_end_all_cmd
);
4821 install_node(&srv6_locs_node
);
4822 install_element(SRV6_LOCS_NODE
, &srv6_locator_cmd
);
4823 install_element(SRV6_LOCS_NODE
, &exit_srv6_locs_config_cmd
);
4824 install_element(SRV6_LOCS_NODE
, &vtysh_end_all_cmd
);
4826 install_node(&srv6_loc_node
);
4827 install_element(SRV6_LOC_NODE
, &exit_srv6_loc_config_cmd
);
4828 install_element(SRV6_LOC_NODE
, &vtysh_end_all_cmd
);
4830 install_element(ENABLE_NODE
, &vtysh_show_running_config_cmd
);
4831 install_element(ENABLE_NODE
, &vtysh_copy_running_config_cmd
);
4832 install_element(ENABLE_NODE
, &vtysh_copy_to_running_cmd
);
4834 /* "write terminal" command. */
4835 install_element(ENABLE_NODE
, &vtysh_write_terminal_cmd
);
4837 install_element(CONFIG_NODE
, &vtysh_integrated_config_cmd
);
4838 install_element(CONFIG_NODE
, &no_vtysh_integrated_config_cmd
);
4840 /* "write memory" command. */
4841 install_element(ENABLE_NODE
, &vtysh_write_memory_cmd
);
4843 install_element(CONFIG_NODE
, &vtysh_terminal_paginate_cmd
);
4844 install_element(VIEW_NODE
, &vtysh_terminal_paginate_cmd
);
4845 install_element(VIEW_NODE
, &vtysh_terminal_length_cmd
);
4846 install_element(VIEW_NODE
, &vtysh_terminal_no_length_cmd
);
4847 install_element(VIEW_NODE
, &vtysh_show_daemons_cmd
);
4849 install_element(VIEW_NODE
, &vtysh_terminal_monitor_cmd
);
4850 install_element(VIEW_NODE
, &no_vtysh_terminal_monitor_cmd
);
4852 install_element(VIEW_NODE
, &vtysh_ping_cmd
);
4853 install_element(VIEW_NODE
, &vtysh_ping_ip_cmd
);
4854 install_element(VIEW_NODE
, &vtysh_traceroute_cmd
);
4855 install_element(VIEW_NODE
, &vtysh_traceroute_ip_cmd
);
4856 install_element(VIEW_NODE
, &vtysh_mtrace_cmd
);
4857 install_element(VIEW_NODE
, &vtysh_ping6_cmd
);
4858 install_element(VIEW_NODE
, &vtysh_traceroute6_cmd
);
4859 #if defined(HAVE_SHELL_ACCESS)
4860 install_element(VIEW_NODE
, &vtysh_telnet_cmd
);
4861 install_element(VIEW_NODE
, &vtysh_telnet_port_cmd
);
4862 install_element(VIEW_NODE
, &vtysh_ssh_cmd
);
4864 #if defined(HAVE_SHELL_ACCESS)
4865 install_element(ENABLE_NODE
, &vtysh_start_shell_cmd
);
4866 install_element(ENABLE_NODE
, &vtysh_start_bash_cmd
);
4867 install_element(ENABLE_NODE
, &vtysh_start_zsh_cmd
);
4871 install_element(VIEW_NODE
, &vtysh_show_error_code_cmd
);
4872 install_element(ENABLE_NODE
, &vtysh_show_debugging_cmd
);
4873 install_element(ENABLE_NODE
, &vtysh_show_debugging_hashtable_cmd
);
4874 install_element(ENABLE_NODE
, &vtysh_debug_all_cmd
);
4875 install_element(CONFIG_NODE
, &vtysh_debug_all_cmd
);
4876 install_element(ENABLE_NODE
, &vtysh_debug_memstats_cmd
);
4877 install_element(CONFIG_NODE
, &vtysh_debug_memstats_cmd
);
4878 install_element(ENABLE_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4879 install_element(CONFIG_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4882 install_element(ENABLE_NODE
, &show_config_running_cmd
);
4883 install_element(ENABLE_NODE
, &show_yang_operational_data_cmd
);
4884 install_element(ENABLE_NODE
, &show_yang_module_cmd
);
4885 install_element(ENABLE_NODE
, &show_yang_module_detail_cmd
);
4886 install_element(ENABLE_NODE
, &debug_nb_cmd
);
4887 install_element(CONFIG_NODE
, &debug_nb_cmd
);
4889 /* misc lib show commands */
4890 install_element(VIEW_NODE
, &vtysh_show_history_cmd
);
4891 install_element(VIEW_NODE
, &vtysh_show_memory_cmd
);
4892 install_element(VIEW_NODE
, &vtysh_show_modules_cmd
);
4893 install_element(VIEW_NODE
, &vtysh_show_work_queues_cmd
);
4894 install_element(VIEW_NODE
, &vtysh_show_work_queues_daemon_cmd
);
4895 install_element(VIEW_NODE
, &vtysh_show_thread_cmd
);
4896 install_element(VIEW_NODE
, &vtysh_show_poll_cmd
);
4897 install_element(VIEW_NODE
, &vtysh_show_thread_timer_cmd
);
4900 install_element(VIEW_NODE
, &vtysh_show_logging_cmd
);
4902 install_element(CONFIG_NODE
, &vtysh_service_password_encrypt_cmd
);
4903 install_element(CONFIG_NODE
, &no_vtysh_service_password_encrypt_cmd
);
4905 install_element(CONFIG_NODE
, &vtysh_password_cmd
);
4906 install_element(CONFIG_NODE
, &no_vtysh_password_cmd
);
4907 install_element(CONFIG_NODE
, &vtysh_enable_password_cmd
);
4908 install_element(CONFIG_NODE
, &no_vtysh_enable_password_cmd
);