1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Virtual terminal interface shell.
3 * Copyright (C) 2000 Kunihiro Ishiguro
11 #include <sys/resource.h>
14 /* readline carries some ancient definitions around */
15 #pragma GCC diagnostic push
16 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
17 #include <readline/readline.h>
18 #include <readline/history.h>
19 #pragma GCC diagnostic pop
30 #include "vtysh/vtysh.h"
31 #include "vtysh/vtysh_daemons.h"
35 #include "command_graph.h"
39 #include "bgpd/bgp_vty.h"
41 DEFINE_MTYPE_STATIC(MVTYSH
, VTYSH_CMD
, "Vtysh cmd copy");
46 /* VTY shell pager name. */
47 char *vtysh_pager_name
= NULL
;
49 /* VTY should add timestamp */
50 bool vtysh_add_timestamp
;
52 /* VTY shell client structure */
57 char path
[MAXPATHLEN
];
58 struct vtysh_client
*next
;
60 struct thread
*log_reader
;
65 static bool stderr_tty
;
66 static bool stderr_stdout_same
;
68 /* Some utility functions for working on vtysh-specific vty tasks */
70 static FILE *vty_open_pager(struct vty
*vty
)
75 if (!vtysh_pager_name
)
78 vty
->of_saved
= vty
->of
;
79 vty
->of
= popen(vtysh_pager_name
, "w");
80 if (vty
->of
== NULL
) {
81 vty
->of
= vty
->of_saved
;
91 static int vty_close_pager(struct vty
*vty
)
97 if (pclose(vty
->of
) == -1) {
102 vty
->of
= vty
->of_saved
;
103 vty
->is_paged
= false;
108 static void vtysh_pager_envdef(bool fallback
)
112 pager_defined
= getenv("VTYSH_PAGER");
115 vtysh_pager_name
= strdup(pager_defined
);
117 vtysh_pager_name
= strdup(VTYSH_PAGER
);
122 struct vtysh_client vtysh_client
[] = {
123 {.name
= "zebra", .flag
= VTYSH_ZEBRA
},
124 {.name
= "ripd", .flag
= VTYSH_RIPD
},
125 {.name
= "ripngd", .flag
= VTYSH_RIPNGD
},
126 {.name
= "ospfd", .flag
= VTYSH_OSPFD
},
127 {.name
= "ospf6d", .flag
= VTYSH_OSPF6D
},
128 {.name
= "ldpd", .flag
= VTYSH_LDPD
},
129 {.name
= "bgpd", .flag
= VTYSH_BGPD
},
130 {.name
= "isisd", .flag
= VTYSH_ISISD
},
131 {.name
= "pimd", .flag
= VTYSH_PIMD
},
132 {.name
= "nhrpd", .flag
= VTYSH_NHRPD
},
133 {.name
= "eigrpd", .flag
= VTYSH_EIGRPD
},
134 {.name
= "babeld", .flag
= VTYSH_BABELD
},
135 {.name
= "sharpd", .flag
= VTYSH_SHARPD
},
136 {.name
= "fabricd", .flag
= VTYSH_FABRICD
},
137 {.name
= "watchfrr", .flag
= VTYSH_WATCHFRR
},
138 {.name
= "pbrd", .flag
= VTYSH_PBRD
},
139 {.name
= "staticd", .flag
= VTYSH_STATICD
},
140 {.name
= "bfdd", .flag
= VTYSH_BFDD
},
141 {.name
= "vrrpd", .flag
= VTYSH_VRRPD
},
142 {.name
= "pathd", .flag
= VTYSH_PATHD
},
143 {.name
= "pim6d", .flag
= VTYSH_PIM6D
},
146 /* Searches for client by name, returns index */
147 static int vtysh_client_lookup(const char *name
)
151 for (unsigned int i
= 0; i
< array_size(vtysh_client
); i
++) {
152 if (strmatch(vtysh_client
[i
].name
, name
)) {
161 enum vtysh_write_integrated vtysh_write_integrated
=
162 WRITE_INTEGRATED_UNSPECIFIED
;
164 static int vtysh_reconnect(struct vtysh_client
*vclient
);
166 static void vclient_close(struct vtysh_client
*vclient
)
168 if (vclient
->fd
>= 0) {
171 "Warning: closing connection to %s because of an I/O error!\n",
174 /* indicate as candidate for reconnect */
175 vclient
->fd
= VTYSH_WAS_ACTIVE
;
179 static ssize_t
vtysh_client_receive(struct vtysh_client
*vclient
, char *buf
,
180 size_t bufsz
, int *pass_fd
)
182 struct iovec iov
[1] = {
189 uint8_t buf
[CMSG_SPACE(sizeof(int))];
190 struct cmsghdr align
;
194 .msg_iovlen
= array_size(iov
),
195 .msg_control
= u
.buf
,
196 .msg_controllen
= sizeof(u
.buf
),
198 struct cmsghdr
*cmh
= CMSG_FIRSTHDR(&mh
);
201 cmh
->cmsg_level
= SOL_SOCKET
;
202 cmh
->cmsg_type
= SCM_RIGHTS
;
203 cmh
->cmsg_len
= CMSG_LEN(sizeof(int));
204 memset(CMSG_DATA(cmh
), -1, sizeof(int));
207 ret
= recvmsg(vclient
->fd
, &mh
, 0);
208 if (ret
>= 0 || (errno
!= EINTR
&& errno
!= EAGAIN
))
212 if (cmh
->cmsg_len
== CMSG_LEN(sizeof(int))) {
215 memcpy(&fd
, CMSG_DATA(cmh
), sizeof(int));
227 * Send a CLI command to a client and read the response.
229 * Output will be printed to vty->of. If you want to suppress output, set that
233 * the client to send the command to
236 * the command to send
239 * if non-null, this will be called with each line of output received from
240 * the client passed in the second parameter
243 * optional first argument to pass to callback
248 static int vtysh_client_run(struct vtysh_client
*vclient
, const char *line
,
249 void (*callback
)(void *, const char *), void *cbarg
,
254 char *buf
= stackbuf
;
255 size_t bufsz
= sizeof(stackbuf
);
256 char *bufvalid
, *end
= NULL
;
257 char terminator
[3] = {0, 0, 0};
259 /* vclinet was previously active, try to reconnect */
260 if (vclient
->fd
== VTYSH_WAS_ACTIVE
) {
261 ret
= vtysh_reconnect(vclient
);
269 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
271 /* close connection and try to reconnect */
272 vclient_close(vclient
);
273 ret
= vtysh_reconnect(vclient
);
277 ret
= write(vclient
->fd
, line
, strlen(line
) + 1);
286 nread
= vtysh_client_receive(
287 vclient
, bufvalid
, buf
+ bufsz
- bufvalid
- 1, pass_fd
);
289 if (nread
< 0 && (errno
== EINTR
|| errno
== EAGAIN
))
295 "vtysh: error reading from %s: %s (%d)",
296 vclient
->name
, safe_strerror(errno
),
303 /* Null terminate so we may pass this to *printf later. */
307 * We expect string output from daemons, so instead of looking
308 * for the full 3 null bytes of the terminator, we check for
309 * just one instead and assume it is the first byte of the
310 * terminator. The presence of the full terminator is checked
313 if (bufvalid
- buf
>= 4)
314 end
= memmem(bufvalid
- 4, 4, "\0", 1);
317 * calculate # bytes we have, up to & not including the
318 * terminator if present
320 size_t textlen
= (end
? end
: bufvalid
) - buf
;
323 /* feed line processing callback if present */
324 while (callback
&& bufvalid
> buf
&& (end
> buf
|| !end
)) {
325 textlen
= (end
? end
: bufvalid
) - buf
;
326 char *eol
= memchr(buf
, '\n', textlen
);
332 * no line break, end of input, no text left
333 * before end; nothing to write
337 /* no nl, end of input, but some text left */
339 else if (bufvalid
== buf
+ bufsz
- 1) {
341 * no nl, no end of input, no buffer space;
347 if (buf
== stackbuf
) {
348 new = XMALLOC(MTYPE_TMP
, bufsz
);
349 memcpy(new, stackbuf
, sizeof(stackbuf
));
351 new = XREALLOC(MTYPE_TMP
, buf
, bufsz
);
353 bufvalid
= bufvalid
- buf
+ new;
355 /* if end != NULL, we won't be reading more
365 /* eol is at line end now, either \n => \0 or \0\0\0 */
366 assert(eol
&& eol
<= bufvalid
);
369 vty_out(vty
, "%s\n", buf
);
371 callback(cbarg
, buf
);
373 /* shift back data and adjust bufvalid */
374 memmove(buf
, eol
, bufvalid
- eol
);
375 bufvalid
-= eol
- buf
;
380 /* else if no callback, dump raw */
383 vty_out(vty
, "%s", buf
);
384 memmove(buf
, buf
+ textlen
, bufvalid
- buf
- textlen
);
390 * ----------------------------------------------------
391 * At this point `buf` should be in one of two states:
392 * - Empty (i.e. buf == bufvalid)
393 * - Contains up to 4 bytes of the terminator
394 * ----------------------------------------------------
396 assert(((buf
== bufvalid
)
397 || (bufvalid
- buf
<= 4 && buf
[0] == 0x00)));
400 /* if we have the terminator, break */
401 if (end
&& bufvalid
- buf
== 4) {
402 assert(!memcmp(buf
, terminator
, 3));
411 vclient_close(vclient
);
415 XFREE(MTYPE_TMP
, buf
);
419 static int vtysh_client_run_all(struct vtysh_client
*head_client
,
420 const char *line
, int continue_on_err
,
421 void (*callback
)(void *, const char *),
424 struct vtysh_client
*client
;
425 int rc
, rc_all
= CMD_SUCCESS
;
426 int correct_instance
= 0, wrong_instance
= 0;
428 for (client
= head_client
; client
; client
= client
->next
) {
429 rc
= vtysh_client_run(client
, line
, callback
, cbarg
, NULL
);
430 if (rc
== CMD_NOT_MY_INSTANCE
) {
436 if (rc
!= CMD_SUCCESS
) {
437 if (!continue_on_err
)
442 if (wrong_instance
&& !correct_instance
&& vty
->of
) {
444 "%% [%s]: command ignored as it targets an instance that is not running\n",
446 rc_all
= CMD_WARNING_CONFIG_FAILED
;
452 * Execute command against all daemons.
455 * where to start walking in the daemon list
458 * the specific command to execute
463 static int vtysh_client_execute(struct vtysh_client
*head_client
,
466 return vtysh_client_run_all(head_client
, line
, 0, NULL
, NULL
);
469 /* Execute by name */
470 static int vtysh_client_execute_name(const char *name
, const char *line
)
472 int ret
= CMD_SUCCESS
;
475 idx_client
= vtysh_client_lookup(name
);
476 if (idx_client
!= -1)
477 ret
= vtysh_client_execute(&vtysh_client
[idx_client
], line
);
479 vty_out(vty
, "Client not found\n");
487 * Retrieve all running config from daemons and parse it with the vtysh config
488 * parser. Returned output is not displayed to the user.
491 * where to start walking in the daemon list
494 * the specific command to execute
496 static void vtysh_client_config(struct vtysh_client
*head_client
, char *line
)
498 /* watchfrr currently doesn't load any config, and has some hardcoded
499 * settings that show up in "show run". skip it here (for now at
500 * least) so we don't get that mangled up in config-write.
502 if (head_client
->flag
== VTYSH_WATCHFRR
)
505 /* suppress output to user */
506 vty
->of_saved
= vty
->of
;
508 vtysh_client_run_all(head_client
, line
, 1, vtysh_config_parse_line
,
510 vty
->of
= vty
->of_saved
;
513 /* Command execution over the vty interface. */
514 static int vtysh_execute_func(const char *line
, int pager
)
519 const struct cmd_element
*cmd
;
521 int saved_ret
, saved_node
;
523 /* Split readline string up into the vector. */
524 vline
= cmd_make_strvec(line
);
529 if (vtysh_add_timestamp
&& strncmp(line
, "exit", 4)) {
532 (void)frr_timestamp(3, ts
, sizeof(ts
));
533 vty_out(vty
, "%% %s\n\n", ts
);
536 saved_ret
= ret
= cmd_execute(vty
, line
, &cmd
, 1);
537 saved_node
= vty
->node
;
540 * If command doesn't succeeded in current node, try to walk up in node
541 * tree. Changing vty->node is enough to try it just out without actual
542 * walkup in the vtysh.
544 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
545 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
546 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
547 && vty
->node
> CONFIG_NODE
) {
548 vty
->node
= node_parent(vty
->node
);
549 ret
= cmd_execute(vty
, line
, &cmd
, 1);
553 vty
->node
= saved_node
;
556 * If command succeeded in any other node than current (tried > 0) we
557 * have to move into node in the vtysh where it succeeded.
559 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
560 || ret
== CMD_WARNING
) {
562 vtysh_execute("exit");
565 * If command didn't succeed in any node, continue with return value
572 cmd_free_strvec(vline
);
577 case CMD_WARNING_CONFIG_FAILED
:
578 if (vty
->type
== VTY_FILE
)
579 vty_out(vty
, "Warning...\n");
581 case CMD_ERR_AMBIGUOUS
:
582 vty_out(vty
, "%% Ambiguous command: %s\n", line
);
584 case CMD_ERR_NO_MATCH
:
585 vty_out(vty
, "%% Unknown command: %s\n", line
);
587 case CMD_ERR_INCOMPLETE
:
588 vty_out(vty
, "%% Command incomplete: %s\n", line
);
590 case CMD_SUCCESS_DAEMON
: {
592 * FIXME: Don't open pager for exit commands. popen() causes
593 * problems if exited from vtysh at all. This hack shouldn't
594 * cause any problem but is really ugly.
596 if (pager
&& strncmp(line
, "exit", 4))
599 if (!strcmp(cmd
->string
, "configure")) {
600 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
601 cmd_stat
= vtysh_client_execute(
602 &vtysh_client
[i
], line
);
603 if (cmd_stat
== CMD_WARNING
)
609 vline
= cmd_make_strvec(line
);
614 vty_close_pager(vty
);
618 ret
= cmd_execute_command(vline
, vty
, &cmd
, 1);
619 cmd_free_strvec(vline
);
620 if (ret
!= CMD_SUCCESS_DAEMON
)
622 } else if (cmd
->func
) {
623 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
628 cmd_stat
= CMD_SUCCESS
;
629 struct vtysh_client
*vc
;
630 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
631 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
632 if (vtysh_client
[i
].fd
< 0
633 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
634 for (vc
= &vtysh_client
[i
]; vc
;
636 if (vc
->fd
== VTYSH_WAS_ACTIVE
)
639 if (vtysh_client
[i
].fd
< 0
640 && (cmd
->daemon
== vtysh_client
[i
].flag
)) {
641 bool any_inst
= false;
642 for (vc
= &vtysh_client
[i
]; vc
;
648 "%s is not running\n",
649 vtysh_client
[i
].name
);
650 cmd_stat
= CMD_ERR_NO_DAEMON
;
654 cmd_stat
= vtysh_client_execute(
655 &vtysh_client
[i
], line
);
656 if (cmd_stat
!= CMD_SUCCESS
)
660 if (cmd_stat
!= CMD_SUCCESS
&& cmd_stat
!= CMD_ERR_NO_DAEMON
)
664 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
668 vty_close_pager(vty
);
673 int vtysh_execute_no_pager(const char *line
)
675 return vtysh_execute_func(line
, 0);
678 int vtysh_execute(const char *line
)
680 return vtysh_execute_func(line
, 1);
683 static char *trim(char *s
)
694 while (end
>= s
&& isspace((unsigned char)*end
))
698 while (*s
&& isspace((unsigned char)*s
))
704 int vtysh_mark_file(const char *filename
)
711 const struct cmd_element
*cmd
;
712 int saved_ret
, prev_node
;
714 char *vty_buf_copy
= NULL
;
715 char *vty_buf_trimmed
= NULL
;
717 if (strncmp("-", filename
, 1) == 0)
720 confp
= fopen(filename
, "r");
723 fprintf(stderr
, "%% Can't open config file %s due to '%s'.\n",
724 filename
, safe_strerror(errno
));
725 return CMD_ERR_NO_FILE
;
729 vty
->wfd
= STDOUT_FILENO
;
730 vty
->type
= VTY_TERM
;
731 vty
->node
= CONFIG_NODE
;
733 vtysh_execute_no_pager("enable");
734 vtysh_execute_no_pager("configure");
735 vty_buf_copy
= XCALLOC(MTYPE_VTYSH_CMD
, VTY_BUFSIZ
);
737 while (fgets(vty
->buf
, VTY_BUFSIZ
, confp
)) {
740 strlcpy(vty_buf_copy
, vty
->buf
, VTY_BUFSIZ
);
741 vty_buf_trimmed
= trim(vty_buf_copy
);
743 if (vty_buf_trimmed
[0] == '!' || vty_buf_trimmed
[0] == '#') {
744 vty_out(vty
, "%s", vty
->buf
);
748 /* Split readline string up into the vector. */
749 vline
= cmd_make_strvec(vty
->buf
);
752 vty_out(vty
, "%s", vty
->buf
);
757 * Ignore the "end" lines, we will generate these where
760 if (strlen(vty_buf_trimmed
) == 3
761 && strncmp("end", vty_buf_trimmed
, 3) == 0) {
762 cmd_free_strvec(vline
);
766 prev_node
= vty
->node
;
767 saved_ret
= ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
770 * If command doesn't succeeded in current node, try to walk up
771 * in node tree. Changing vty->node is enough to try it just
772 * out without actual walkup in the vtysh.
774 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_SUCCESS_DAEMON
775 && ret
!= CMD_WARNING
&& ret
!= CMD_WARNING_CONFIG_FAILED
776 && ret
!= CMD_ERR_AMBIGUOUS
&& ret
!= CMD_ERR_INCOMPLETE
777 && vty
->node
> CONFIG_NODE
) {
778 vty
->node
= node_parent(vty
->node
);
779 ret
= cmd_execute_command_strict(vline
, vty
, &cmd
);
784 * If command succeeded in any other node than current (tried >
785 * 0) we have to move into node in the vtysh where it
788 if (ret
== CMD_SUCCESS
|| ret
== CMD_SUCCESS_DAEMON
789 || ret
== CMD_WARNING
) {
791 vty_out(vty
, "exit\n");
794 * If command didn't succeed in any node, continue with return
795 * value from first try.
799 vty
->node
= prev_node
;
802 cmd_free_strvec(vline
);
805 case CMD_WARNING_CONFIG_FAILED
:
806 if (vty
->type
== VTY_FILE
)
807 fprintf(stderr
, "line %d: Warning...: %s\n",
811 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
813 case CMD_ERR_AMBIGUOUS
:
814 fprintf(stderr
, "line %d: %% Ambiguous command: %s\n",
818 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
819 return CMD_ERR_AMBIGUOUS
;
820 case CMD_ERR_NO_MATCH
:
821 fprintf(stderr
, "line %d: %% Unknown command: %s\n",
825 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
826 return CMD_ERR_NO_MATCH
;
827 case CMD_ERR_INCOMPLETE
:
828 fprintf(stderr
, "line %d: %% Command incomplete: %s\n",
832 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
833 return CMD_ERR_INCOMPLETE
;
835 vty_out(vty
, "%s", vty
->buf
);
836 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
837 vty_out(vty
, "end\n");
839 case CMD_SUCCESS_DAEMON
: {
842 vty_out(vty
, "%s", vty
->buf
);
843 if (strmatch(vty_buf_trimmed
, "exit-vrf"))
844 vty_out(vty
, "end\n");
845 cmd_stat
= vtysh_client_execute(&vtysh_client
[0],
847 if (cmd_stat
!= CMD_SUCCESS
)
851 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
855 /* This is the end */
856 vty_out(vty
, "\nend\n");
858 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
866 /* Configuration make from file. */
867 int vtysh_config_from_file(struct vty
*vty
, FILE *fp
)
870 const struct cmd_element
*cmd
;
872 /* once we have an error, we remember & return that */
873 int retcode
= CMD_SUCCESS
;
874 char *vty_buf_copy
= XCALLOC(MTYPE_VTYSH_CMD
, VTY_BUFSIZ
);
875 char *vty_buf_trimmed
= NULL
;
877 while (fgets(vty
->buf
, VTY_BUFSIZ
, fp
)) {
880 strlcpy(vty_buf_copy
, vty
->buf
, VTY_BUFSIZ
);
881 vty_buf_trimmed
= trim(vty_buf_copy
);
884 * Ignore the "end" lines, we will generate these where
885 * appropriate, otherwise we never execute
886 * XFRR_end_configuration, and start/end markers do not work.
888 if (strmatch(vty_buf_trimmed
, "end"))
891 ret
= command_config_read_one_line(vty
, &cmd
, lineno
, 1);
895 case CMD_WARNING_CONFIG_FAILED
:
896 if (vty
->type
== VTY_FILE
)
897 fprintf(stderr
, "line %d: Warning[%d]...: %s\n",
898 lineno
, vty
->node
, vty
->buf
);
902 case CMD_ERR_AMBIGUOUS
:
904 "line %d: %% Ambiguous command[%d]: %s\n",
905 lineno
, vty
->node
, vty
->buf
);
906 retcode
= CMD_ERR_AMBIGUOUS
;
908 case CMD_ERR_NO_MATCH
:
909 fprintf(stderr
, "line %d: %% Unknown command[%d]: %s",
910 lineno
, vty
->node
, vty
->buf
);
911 retcode
= CMD_ERR_NO_MATCH
;
913 case CMD_ERR_INCOMPLETE
:
915 "line %d: %% Command incomplete[%d]: %s\n",
916 lineno
, vty
->node
, vty
->buf
);
917 retcode
= CMD_ERR_INCOMPLETE
;
919 case CMD_SUCCESS_DAEMON
: {
921 int cmd_stat
= CMD_SUCCESS
;
923 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
924 if (cmd
->daemon
& vtysh_client
[i
].flag
) {
925 cmd_stat
= vtysh_client_execute(
926 &vtysh_client
[i
], vty
->buf
);
928 * CMD_WARNING - Can mean that the
929 * command was parsed successfully but
930 * it was already entered in a few
931 * spots. As such if we receive a
932 * CMD_WARNING from a daemon we
933 * shouldn't stop talking to the other
934 * daemons for the particular command.
936 if (cmd_stat
!= CMD_SUCCESS
937 && cmd_stat
!= CMD_WARNING
) {
939 "line %d: Failure to communicate[%d] to %s, line: %s\n",
941 vtysh_client
[i
].name
,
948 if (cmd_stat
!= CMD_SUCCESS
)
952 (*cmd
->func
)(cmd
, vty
, 0, NULL
);
957 XFREE(MTYPE_VTYSH_CMD
, vty_buf_copy
);
963 * Function processes cli commands terminated with '?' character when entered
964 * through either 'vtysh' or 'vtysh -c' interfaces.
966 static int vtysh_process_questionmark(const char *input
, int input_len
)
970 vector vline
, describe
;
971 struct cmd_token
*token
;
976 vline
= cmd_make_strvec(input
);
978 /* In case of '> ?'. */
980 vline
= vector_init(1);
981 vector_set(vline
, NULL
);
982 } else if (input_len
&& isspace((unsigned char)input
[input_len
- 1]))
983 vector_set(vline
, NULL
);
985 describe
= cmd_describe_command(vline
, vty
, &ret
);
987 /* Ambiguous and no match error. */
989 case CMD_ERR_AMBIGUOUS
:
990 cmd_free_strvec(vline
);
991 vector_free(describe
);
992 vty_out(vty
, "%% Ambiguous command.\n");
995 case CMD_ERR_NO_MATCH
:
996 cmd_free_strvec(vline
);
998 vector_free(describe
);
999 vty_out(vty
, "%% There is no matched command.\n");
1004 /* Get width of command string. */
1006 for (i
= 0; i
< vector_active(describe
); i
++)
1007 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1008 if (token
->text
[0] == '\0')
1011 int len
= strlen(token
->text
);
1017 for (i
= 0; i
< vector_active(describe
); i
++)
1018 if ((token
= vector_slot(describe
, i
)) != NULL
) {
1020 vty_out(vty
, " %-s\n", token
->text
);
1022 vty_out(vty
, " %-*s %s\n", width
, token
->text
,
1025 if (IS_VARYING_TOKEN(token
->type
)) {
1026 const char *ref
= vector_slot(
1027 vline
, vector_active(vline
) - 1);
1029 vector varcomps
= vector_init(VECTOR_MIN_SIZE
);
1030 cmd_variable_complete(token
, ref
, varcomps
);
1032 if (vector_active(varcomps
) > 0) {
1034 rl_get_screen_size(&rows
, &cols
);
1036 char *ac
= cmd_variable_comp2str(
1038 vty_out(vty
, "%s\n", ac
);
1039 XFREE(MTYPE_TMP
, ac
);
1042 vector_free(varcomps
);
1046 cmd_free_strvec(vline
);
1047 vector_free(describe
);
1053 * Entry point for user commands terminated with '?' character and typed through
1054 * the usual vtysh's stdin interface. This is the function being registered with
1057 static int vtysh_rl_describe(int a
, int b
)
1063 ret
= vtysh_process_questionmark(rl_line_buffer
, rl_end
);
1070 * Function in charged of processing vtysh instructions terminating with '?'
1071 * character and received through the 'vtysh -c' interface. If user's
1072 * instruction is well-formatted, we will call the same processing routine
1073 * utilized by the traditional vtysh's stdin interface.
1075 int vtysh_execute_command_questionmark(char *input
)
1077 int input_len
, qmark_count
= 0;
1080 if (!(input
&& *input
))
1083 /* Finding out question_mark count and strlen */
1084 for (str
= input
; *str
; ++str
) {
1088 input_len
= str
- input
;
1091 * Verify that user's input terminates in '?' and that patterns such as
1092 * 'cmd ? subcmd ?' are prevented.
1094 if (qmark_count
!= 1 || input
[input_len
- 1] != '?')
1098 * Questionmark-processing function is not expecting to receive '?'
1099 * character in input string.
1101 input
[input_len
- 1] = '\0';
1103 return vtysh_process_questionmark(input
, input_len
- 1);
1106 /* Result of cmd_complete_command() call will be stored here
1107 * and used in new_completion() in order to put the space in
1108 * correct places only. */
1109 int complete_status
;
1111 static char *command_generator(const char *text
, int state
)
1114 static char **matched
= NULL
;
1115 static int index
= 0;
1121 if (vty
->node
== AUTH_NODE
|| vty
->node
== AUTH_ENABLE_NODE
)
1124 vline
= cmd_make_strvec(rl_line_buffer
);
1129 isspace((unsigned char)rl_line_buffer
[rl_end
- 1]))
1130 vector_set(vline
, NULL
);
1132 matched
= cmd_complete_command(vline
, vty
, &complete_status
);
1133 cmd_free_strvec(vline
);
1136 if (matched
&& matched
[index
]) {
1137 XCOUNTFREE(MTYPE_COMPLETION
, matched
[index
]);
1138 return matched
[index
++];
1141 XFREE(MTYPE_TMP
, matched
);
1146 static char **new_completion(const char *text
, int start
, int end
)
1150 matches
= rl_completion_matches(text
, command_generator
);
1154 if (complete_status
!= CMD_COMPLETE_FULL_MATCH
)
1155 /* only append a space on full match */
1156 rl_completion_append_character
= '\0';
1162 /* Vty node structures. */
1164 static struct cmd_node bgp_node
= {
1167 .parent_node
= CONFIG_NODE
,
1168 .prompt
= "%s(config-router)# ",
1170 #endif /* HAVE_BGPD */
1172 static struct cmd_node rip_node
= {
1175 .parent_node
= CONFIG_NODE
,
1176 .prompt
= "%s(config-router)# ",
1180 static struct cmd_node isis_node
= {
1183 .parent_node
= CONFIG_NODE
,
1184 .prompt
= "%s(config-router)# ",
1186 #endif /* HAVE_ISISD */
1189 static struct cmd_node openfabric_node
= {
1190 .name
= "openfabric",
1191 .node
= OPENFABRIC_NODE
,
1192 .parent_node
= CONFIG_NODE
,
1193 .prompt
= "%s(config-router)# ",
1195 #endif /* HAVE_FABRICD */
1197 static struct cmd_node interface_node
= {
1198 .name
= "interface",
1199 .node
= INTERFACE_NODE
,
1200 .parent_node
= CONFIG_NODE
,
1201 .prompt
= "%s(config-if)# ",
1204 static struct cmd_node pw_node
= {
1207 .parent_node
= CONFIG_NODE
,
1208 .prompt
= "%s(config-pw)# ",
1211 static struct cmd_node segment_routing_node
= {
1212 .name
= "segment-routing",
1213 .node
= SEGMENT_ROUTING_NODE
,
1214 .parent_node
= CONFIG_NODE
,
1215 .prompt
= "%s(config-sr)# ",
1218 #if defined(HAVE_PATHD)
1219 static struct cmd_node sr_traffic_eng_node
= {
1220 .name
= "sr traffic-eng",
1221 .node
= SR_TRAFFIC_ENG_NODE
,
1222 .parent_node
= SEGMENT_ROUTING_NODE
,
1223 .prompt
= "%s(config-sr-te)# ",
1226 static struct cmd_node srte_segment_list_node
= {
1227 .name
= "srte segment-list",
1228 .node
= SR_SEGMENT_LIST_NODE
,
1229 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1230 .prompt
= "%s(config-sr-te-segment-list)# ",
1233 static struct cmd_node srte_policy_node
= {
1234 .name
= "srte policy",
1235 .node
= SR_POLICY_NODE
,
1236 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1237 .prompt
= "%s(config-sr-te-policy)# ",
1240 static struct cmd_node srte_candidate_dyn_node
= {
1241 .name
= "srte candidate-dyn",
1242 .node
= SR_CANDIDATE_DYN_NODE
,
1243 .parent_node
= SR_POLICY_NODE
,
1244 .prompt
= "%s(config-sr-te-candidate)# ",
1247 static struct cmd_node pcep_node
= {
1248 .name
= "srte pcep",
1250 .parent_node
= SR_TRAFFIC_ENG_NODE
,
1251 .prompt
= "%s(config-sr-te-pcep)# "
1254 static struct cmd_node pcep_pcc_node
= {
1255 .name
= "srte pcep pcc",
1256 .node
= PCEP_PCC_NODE
,
1257 .parent_node
= PCEP_NODE
,
1258 .prompt
= "%s(config-sr-te-pcep-pcc)# ",
1261 static struct cmd_node pcep_pce_node
= {
1262 .name
= "srte pcep pce-peer",
1263 .node
= PCEP_PCE_NODE
,
1264 .parent_node
= PCEP_NODE
,
1265 .prompt
= "%s(config-sr-te-pcep-pce-peer)# ",
1268 static struct cmd_node pcep_pce_config_node
= {
1269 .name
= "srte pcep pce-config",
1270 .node
= PCEP_PCE_CONFIG_NODE
,
1271 .parent_node
= PCEP_NODE
,
1272 .prompt
= "%s(pcep-sr-te-pcep-pce-config)# ",
1274 #endif /* HAVE_PATHD */
1276 static struct cmd_node vrf_node
= {
1279 .parent_node
= CONFIG_NODE
,
1280 .prompt
= "%s(config-vrf)# ",
1283 static struct cmd_node nh_group_node
= {
1284 .name
= "nexthop-group",
1285 .node
= NH_GROUP_NODE
,
1286 .parent_node
= CONFIG_NODE
,
1287 .prompt
= "%s(config-nh-group)# ",
1290 static struct cmd_node rmap_node
= {
1293 .parent_node
= CONFIG_NODE
,
1294 .prompt
= "%s(config-route-map)# ",
1297 static struct cmd_node srv6_node
= {
1300 .parent_node
= SEGMENT_ROUTING_NODE
,
1301 .prompt
= "%s(config-srv6)# ",
1304 static struct cmd_node srv6_locs_node
= {
1305 .name
= "srv6-locators",
1306 .node
= SRV6_LOCS_NODE
,
1307 .parent_node
= SRV6_NODE
,
1308 .prompt
= "%s(config-srv6-locators)# ",
1311 static struct cmd_node srv6_loc_node
= {
1312 .name
= "srv6-locator",
1313 .node
= SRV6_LOC_NODE
,
1314 .parent_node
= SRV6_LOCS_NODE
,
1315 .prompt
= "%s(config-srv6-locator)# ",
1319 static struct cmd_node pbr_map_node
= {
1321 .node
= PBRMAP_NODE
,
1322 .parent_node
= CONFIG_NODE
,
1323 .prompt
= "%s(config-pbr-map)# ",
1325 #endif /* HAVE_PBRD */
1327 static struct cmd_node zebra_node
= {
1330 .parent_node
= CONFIG_NODE
,
1331 .prompt
= "%s(config-router)# ",
1335 static struct cmd_node bgp_vpnv4_node
= {
1336 .name
= "bgp vpnv4",
1337 .node
= BGP_VPNV4_NODE
,
1338 .parent_node
= BGP_NODE
,
1339 .prompt
= "%s(config-router-af)# ",
1343 static struct cmd_node bgp_vpnv6_node
= {
1344 .name
= "bgp vpnv6",
1345 .node
= BGP_VPNV6_NODE
,
1346 .parent_node
= BGP_NODE
,
1347 .prompt
= "%s(config-router-af)# ",
1351 static struct cmd_node bgp_flowspecv4_node
= {
1352 .name
= "bgp ipv4 flowspec",
1353 .node
= BGP_FLOWSPECV4_NODE
,
1354 .parent_node
= BGP_NODE
,
1355 .prompt
= "%s(config-router-af)# ",
1359 static struct cmd_node bgp_flowspecv6_node
= {
1360 .name
= "bgp ipv6 flowspec",
1361 .node
= BGP_FLOWSPECV6_NODE
,
1362 .parent_node
= BGP_NODE
,
1363 .prompt
= "%s(config-router-af)# ",
1367 static struct cmd_node bgp_ipv4_node
= {
1368 .name
= "bgp ipv4 unicast",
1369 .node
= BGP_IPV4_NODE
,
1370 .parent_node
= BGP_NODE
,
1371 .prompt
= "%s(config-router-af)# ",
1375 static struct cmd_node bgp_ipv4m_node
= {
1376 .name
= "bgp ipv4 multicast",
1377 .node
= BGP_IPV4M_NODE
,
1378 .parent_node
= BGP_NODE
,
1379 .prompt
= "%s(config-router-af)# ",
1383 static struct cmd_node bgp_ipv4l_node
= {
1384 .name
= "bgp ipv4 labeled unicast",
1385 .node
= BGP_IPV4L_NODE
,
1386 .parent_node
= BGP_NODE
,
1387 .prompt
= "%s(config-router-af)# ",
1391 static struct cmd_node bgp_ipv6_node
= {
1393 .node
= BGP_IPV6_NODE
,
1394 .parent_node
= BGP_NODE
,
1395 .prompt
= "%s(config-router-af)# ",
1399 static struct cmd_node bgp_ipv6m_node
= {
1400 .name
= "bgp ipv6 multicast",
1401 .node
= BGP_IPV6M_NODE
,
1402 .parent_node
= BGP_NODE
,
1403 .prompt
= "%s(config-router-af)# ",
1407 static struct cmd_node bgp_evpn_node
= {
1409 .node
= BGP_EVPN_NODE
,
1410 .parent_node
= BGP_NODE
,
1411 .prompt
= "%s(config-router-af)# ",
1415 static struct cmd_node bgp_evpn_vni_node
= {
1416 .name
= "bgp evpn vni",
1417 .node
= BGP_EVPN_VNI_NODE
,
1418 .parent_node
= BGP_EVPN_NODE
,
1419 .prompt
= "%s(config-router-af-vni)# ",
1422 static struct cmd_node bgp_ipv6l_node
= {
1423 .name
= "bgp ipv6 labeled unicast",
1424 .node
= BGP_IPV6L_NODE
,
1425 .parent_node
= BGP_NODE
,
1426 .prompt
= "%s(config-router-af)# ",
1430 #ifdef ENABLE_BGP_VNC
1431 static struct cmd_node bgp_vnc_defaults_node
= {
1432 .name
= "bgp vnc defaults",
1433 .node
= BGP_VNC_DEFAULTS_NODE
,
1434 .parent_node
= BGP_NODE
,
1435 .prompt
= "%s(config-router-vnc-defaults)# ",
1438 static struct cmd_node bgp_vnc_nve_group_node
= {
1439 .name
= "bgp vnc nve",
1440 .node
= BGP_VNC_NVE_GROUP_NODE
,
1441 .parent_node
= BGP_NODE
,
1442 .prompt
= "%s(config-router-vnc-nve-group)# ",
1445 static struct cmd_node bgp_vrf_policy_node
= {
1446 .name
= "bgp vrf policy",
1447 .node
= BGP_VRF_POLICY_NODE
,
1448 .parent_node
= BGP_NODE
,
1449 .prompt
= "%s(config-router-vrf-policy)# ",
1452 static struct cmd_node bgp_vnc_l2_group_node
= {
1453 .name
= "bgp vnc l2",
1454 .node
= BGP_VNC_L2_GROUP_NODE
,
1455 .parent_node
= BGP_NODE
,
1456 .prompt
= "%s(config-router-vnc-l2-group)# ",
1458 #endif /* ENABLE_BGP_VNC */
1460 static struct cmd_node bmp_node
= {
1463 .parent_node
= BGP_NODE
,
1464 .prompt
= "%s(config-bgp-bmp)# "
1467 static struct cmd_node bgp_srv6_node
= {
1469 .node
= BGP_SRV6_NODE
,
1470 .parent_node
= BGP_NODE
,
1471 .prompt
= "%s(config-router-srv6)# ",
1473 #endif /* HAVE_BGPD */
1476 static struct cmd_node ospf_node
= {
1479 .parent_node
= CONFIG_NODE
,
1480 .prompt
= "%s(config-router)# ",
1482 #endif /* HAVE_OSPFD */
1485 static struct cmd_node eigrp_node
= {
1488 .parent_node
= CONFIG_NODE
,
1489 .prompt
= "%s(config-router)# ",
1491 #endif /* HAVE_EIGRPD */
1494 static struct cmd_node babel_node
= {
1497 .parent_node
= CONFIG_NODE
,
1498 .prompt
= "%s(config-router)# ",
1500 #endif /* HAVE_BABELD */
1502 static struct cmd_node ripng_node
= {
1505 .parent_node
= CONFIG_NODE
,
1506 .prompt
= "%s(config-router)# ",
1510 static struct cmd_node ospf6_node
= {
1513 .parent_node
= CONFIG_NODE
,
1514 .prompt
= "%s(config-ospf6)# ",
1516 #endif /* HAVE_OSPF6D */
1519 static struct cmd_node ldp_node
= {
1522 .parent_node
= CONFIG_NODE
,
1523 .prompt
= "%s(config-ldp)# ",
1526 static struct cmd_node ldp_ipv4_node
= {
1528 .node
= LDP_IPV4_NODE
,
1529 .parent_node
= LDP_NODE
,
1530 .prompt
= "%s(config-ldp-af)# ",
1533 static struct cmd_node ldp_ipv6_node
= {
1535 .node
= LDP_IPV6_NODE
,
1536 .parent_node
= LDP_NODE
,
1537 .prompt
= "%s(config-ldp-af)# ",
1540 static struct cmd_node ldp_ipv4_iface_node
= {
1541 .name
= "ldp ipv4 interface",
1542 .node
= LDP_IPV4_IFACE_NODE
,
1543 .parent_node
= LDP_IPV4_NODE
,
1544 .prompt
= "%s(config-ldp-af-if)# ",
1547 static struct cmd_node ldp_ipv6_iface_node
= {
1548 .name
= "ldp ipv6 interface",
1549 .node
= LDP_IPV6_IFACE_NODE
,
1550 .parent_node
= LDP_IPV6_NODE
,
1551 .prompt
= "%s(config-ldp-af-if)# ",
1554 static struct cmd_node ldp_l2vpn_node
= {
1555 .name
= "ldp l2vpn",
1556 .node
= LDP_L2VPN_NODE
,
1557 .parent_node
= CONFIG_NODE
,
1558 .prompt
= "%s(config-l2vpn)# ",
1561 static struct cmd_node ldp_pseudowire_node
= {
1563 .node
= LDP_PSEUDOWIRE_NODE
,
1564 .parent_node
= LDP_L2VPN_NODE
,
1565 .prompt
= "%s(config-l2vpn-pw)# ",
1567 #endif /* HAVE_LDPD */
1569 static struct cmd_node keychain_node
= {
1571 .node
= KEYCHAIN_NODE
,
1572 .parent_node
= CONFIG_NODE
,
1573 .prompt
= "%s(config-keychain)# ",
1576 static struct cmd_node keychain_key_node
= {
1577 .name
= "keychain key",
1578 .node
= KEYCHAIN_KEY_NODE
,
1579 .parent_node
= KEYCHAIN_NODE
,
1580 .prompt
= "%s(config-keychain-key)# ",
1583 struct cmd_node link_params_node
= {
1584 .name
= "link-params",
1585 .node
= LINK_PARAMS_NODE
,
1586 .parent_node
= INTERFACE_NODE
,
1587 .prompt
= "%s(config-link-params)# ",
1592 static struct cmd_node rpki_node
= {
1595 .parent_node
= CONFIG_NODE
,
1596 .prompt
= "%s(config-rpki)# ",
1598 #endif /* HAVE_BGPD */
1601 static struct cmd_node bfd_node
= {
1604 .parent_node
= CONFIG_NODE
,
1605 .prompt
= "%s(config-bfd)# ",
1608 static struct cmd_node bfd_peer_node
= {
1610 .node
= BFD_PEER_NODE
,
1611 .parent_node
= BFD_NODE
,
1612 .prompt
= "%s(config-bfd-peer)# ",
1615 static struct cmd_node bfd_profile_node
= {
1616 .name
= "bfd profile",
1617 .node
= BFD_PROFILE_NODE
,
1618 .parent_node
= BFD_NODE
,
1619 .prompt
= "%s(config-bfd-profile)# ",
1621 #endif /* HAVE_BFDD */
1623 /* Defined in lib/vty.c */
1624 extern struct cmd_node vty_node
;
1626 /* When '^Z' is received from vty, move down to the enable mode. */
1627 static int vtysh_end(void)
1629 switch (vty
->node
) {
1632 /* Nothing to do. */
1635 vty
->node
= ENABLE_NODE
;
1641 #include "vtysh/vtysh_clippy.c"
1643 DEFUNSH(VTYSH_REALLYALL
, vtysh_end_all
, vtysh_end_all_cmd
, "end",
1644 "End current mode and change to enable mode\n")
1649 DEFUNSH(VTYSH_ZEBRA
, srv6
, srv6_cmd
,
1651 "Segment-Routing SRv6 configuration\n")
1653 vty
->node
= SRV6_NODE
;
1657 DEFUNSH(VTYSH_ZEBRA
, srv6_locators
, srv6_locators_cmd
,
1659 "Segment-Routing SRv6 locators configuration\n")
1661 vty
->node
= SRV6_LOCS_NODE
;
1665 DEFUNSH(VTYSH_ZEBRA
, srv6_locator
, srv6_locator_cmd
,
1667 "Segment Routing SRv6 locator\n"
1668 "Specify locator-name\n")
1670 vty
->node
= SRV6_LOC_NODE
;
1675 DEFUNSH(VTYSH_BGPD
, router_bgp
, router_bgp_cmd
,
1676 "router bgp [ASNUM [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]",
1677 ROUTER_STR BGP_STR AS_STR
1678 "BGP view\nBGP VRF\n"
1680 "Force the AS notation output\n"
1681 "use 'AA.BB' format for AS 4 byte values\n"
1682 "use 'AA.BB' format for all AS values\n"
1683 "use plain format for all AS values\n")
1685 vty
->node
= BGP_NODE
;
1689 #ifdef KEEP_OLD_VPN_COMMANDS
1690 DEFUNSH(VTYSH_BGPD
, address_family_vpnv4
, address_family_vpnv4_cmd
,
1691 "address-family vpnv4 [unicast]",
1692 "Enter Address Family command mode\n"
1694 BGP_AF_MODIFIER_STR
)
1696 vty
->node
= BGP_VPNV4_NODE
;
1700 DEFUNSH(VTYSH_BGPD
, address_family_vpnv6
, address_family_vpnv6_cmd
,
1701 "address-family vpnv6 [unicast]",
1702 "Enter Address Family command mode\n"
1704 BGP_AF_MODIFIER_STR
)
1706 vty
->node
= BGP_VPNV6_NODE
;
1709 #endif /* KEEP_OLD_VPN_COMMANDS */
1711 DEFUNSH(VTYSH_BGPD
, address_family_ipv4
, address_family_ipv4_cmd
,
1712 "address-family ipv4 [unicast]",
1713 "Enter Address Family command mode\n"
1715 BGP_AF_MODIFIER_STR
)
1717 vty
->node
= BGP_IPV4_NODE
;
1721 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv4
, address_family_flowspecv4_cmd
,
1722 "address-family ipv4 flowspec",
1723 "Enter Address Family command mode\n"
1725 BGP_AF_MODIFIER_STR
)
1727 vty
->node
= BGP_FLOWSPECV4_NODE
;
1731 DEFUNSH(VTYSH_BGPD
, address_family_flowspecv6
, address_family_flowspecv6_cmd
,
1732 "address-family ipv6 flowspec",
1733 "Enter Address Family command mode\n"
1735 BGP_AF_MODIFIER_STR
)
1737 vty
->node
= BGP_FLOWSPECV6_NODE
;
1741 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_multicast
,
1742 address_family_ipv4_multicast_cmd
, "address-family ipv4 multicast",
1743 "Enter Address Family command mode\n"
1745 BGP_AF_MODIFIER_STR
)
1747 vty
->node
= BGP_IPV4M_NODE
;
1751 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_vpn
, address_family_ipv4_vpn_cmd
,
1752 "address-family ipv4 vpn",
1753 "Enter Address Family command mode\n"
1755 BGP_AF_MODIFIER_STR
)
1757 vty
->node
= BGP_VPNV4_NODE
;
1761 DEFUNSH(VTYSH_BGPD
, address_family_ipv4_labeled_unicast
,
1762 address_family_ipv4_labeled_unicast_cmd
,
1763 "address-family ipv4 labeled-unicast",
1764 "Enter Address Family command mode\n"
1766 BGP_AF_MODIFIER_STR
)
1768 vty
->node
= BGP_IPV4L_NODE
;
1772 DEFUNSH(VTYSH_BGPD
, address_family_ipv6
, address_family_ipv6_cmd
,
1773 "address-family ipv6 [unicast]",
1774 "Enter Address Family command mode\n"
1776 BGP_AF_MODIFIER_STR
)
1778 vty
->node
= BGP_IPV6_NODE
;
1782 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_multicast
,
1783 address_family_ipv6_multicast_cmd
, "address-family ipv6 multicast",
1784 "Enter Address Family command mode\n"
1786 BGP_AF_MODIFIER_STR
)
1788 vty
->node
= BGP_IPV6M_NODE
;
1792 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_vpn
, address_family_ipv6_vpn_cmd
,
1793 "address-family ipv6 vpn",
1794 "Enter Address Family command mode\n"
1796 BGP_AF_MODIFIER_STR
)
1798 vty
->node
= BGP_VPNV6_NODE
;
1802 DEFUNSH(VTYSH_BGPD
, address_family_ipv6_labeled_unicast
,
1803 address_family_ipv6_labeled_unicast_cmd
,
1804 "address-family ipv6 labeled-unicast",
1805 "Enter Address Family command mode\n"
1807 BGP_AF_MODIFIER_STR
)
1809 vty
->node
= BGP_IPV6L_NODE
;
1817 "Enable rpki and enter rpki configuration mode\n")
1819 vty
->node
= RPKI_NODE
;
1826 "bmp targets BMPTARGETS",
1827 "BGP Monitoring Protocol\n"
1828 "Create BMP target group\n"
1829 "Name of the BMP target group\n")
1831 vty
->node
= BMP_NODE
;
1838 "segment-routing srv6",
1839 "Segment-Routing configuration\n"
1840 "Segment-Routing SRv6 configuration\n")
1842 vty
->node
= BGP_SRV6_NODE
;
1850 "exit Segment-Routing SRv6 configuration\n")
1852 if (vty
->node
== BGP_SRV6_NODE
)
1853 vty
->node
= BGP_NODE
;
1861 "quit Segment-Routing SRv6 configuration\n")
1863 if (vty
->node
== BGP_SRV6_NODE
)
1864 vty
->node
= BGP_NODE
;
1868 DEFUNSH(VTYSH_BGPD
, address_family_evpn
, address_family_evpn_cmd
,
1869 "address-family <l2vpn evpn>",
1870 "Enter Address Family command mode\n"
1872 BGP_AF_MODIFIER_STR
)
1874 vty
->node
= BGP_EVPN_NODE
;
1878 DEFUNSH(VTYSH_BGPD
, bgp_evpn_vni
, bgp_evpn_vni_cmd
, "vni " CMD_VNI_RANGE
,
1879 "VXLAN Network Identifier\n"
1882 vty
->node
= BGP_EVPN_VNI_NODE
;
1886 #if defined(ENABLE_BGP_VNC)
1887 DEFUNSH(VTYSH_BGPD
, vnc_defaults
, vnc_defaults_cmd
, "vnc defaults",
1888 "VNC/RFP related configuration\n"
1889 "Configure default NVE group\n")
1891 vty
->node
= BGP_VNC_DEFAULTS_NODE
;
1895 DEFUNSH(VTYSH_BGPD
, vnc_nve_group
, vnc_nve_group_cmd
, "vnc nve-group NAME",
1896 "VNC/RFP related configuration\n"
1897 "Configure a NVE group\n"
1900 vty
->node
= BGP_VNC_NVE_GROUP_NODE
;
1904 DEFUNSH(VTYSH_BGPD
, vnc_vrf_policy
, vnc_vrf_policy_cmd
, "vrf-policy NAME",
1905 "Configure a VRF policy group\n"
1908 vty
->node
= BGP_VRF_POLICY_NODE
;
1912 DEFUNSH(VTYSH_BGPD
, vnc_l2_group
, vnc_l2_group_cmd
, "vnc l2-group NAME",
1913 "VNC/RFP related configuration\n"
1914 "Configure a L2 group\n"
1917 vty
->node
= BGP_VNC_L2_GROUP_NODE
;
1921 DEFUNSH(VTYSH_BGPD
, exit_vnc_config
, exit_vnc_config_cmd
, "exit-vnc",
1922 "Exit from VNC configuration mode\n")
1924 if (vty
->node
== BGP_VNC_DEFAULTS_NODE
1925 || vty
->node
== BGP_VNC_NVE_GROUP_NODE
1926 || vty
->node
== BGP_VNC_L2_GROUP_NODE
)
1927 vty
->node
= BGP_NODE
;
1931 DEFUNSH(VTYSH_BGPD
, exit_vrf_policy
, exit_vrf_policy_cmd
, "exit-vrf-policy",
1932 "Exit from VRF policy configuration mode\n")
1934 if (vty
->node
== BGP_VRF_POLICY_NODE
)
1935 vty
->node
= BGP_NODE
;
1939 #endif /* HAVE_BGPD */
1941 DEFUNSH(VTYSH_KEYS
, key_chain
, key_chain_cmd
, "key chain WORD",
1942 "Authentication key management\n"
1943 "Key-chain management\n"
1946 vty
->node
= KEYCHAIN_NODE
;
1950 DEFUNSH(VTYSH_KEYS
, key
, key_cmd
, "key (0-2147483647)",
1952 "Key identifier number\n")
1954 vty
->node
= KEYCHAIN_KEY_NODE
;
1959 DEFUNSH(VTYSH_RIPD
, router_rip
, router_rip_cmd
, "router rip [vrf NAME]",
1960 ROUTER_STR
"RIP\n" VRF_CMD_HELP_STR
)
1962 vty
->node
= RIP_NODE
;
1965 #endif /* HAVE_RIPD */
1968 DEFUNSH(VTYSH_RIPNGD
, router_ripng
, router_ripng_cmd
, "router ripng [vrf NAME]",
1969 ROUTER_STR
"RIPng\n" VRF_CMD_HELP_STR
)
1971 vty
->node
= RIPNG_NODE
;
1974 #endif /* HAVE_RIPNGD */
1977 DEFUNSH(VTYSH_OSPFD
, router_ospf
, router_ospf_cmd
,
1978 "router ospf [(1-65535)] [vrf NAME]",
1979 "Enable a routing process\n"
1980 "Start OSPF configuration\n"
1984 vty
->node
= OSPF_NODE
;
1987 #endif /* HAVE_OSPFD */
1990 DEFUNSH(VTYSH_EIGRPD
, router_eigrp
, router_eigrp_cmd
, "router eigrp (1-65535) [vrf NAME]",
1991 "Enable a routing process\n"
1992 "Start EIGRP configuration\n"
1993 "AS number to use\n"
1996 vty
->node
= EIGRP_NODE
;
1999 #endif /* HAVE_EIGRPD */
2002 DEFUNSH(VTYSH_BABELD
, router_babel
, router_babel_cmd
, "router babel",
2003 "Enable a routing process\n"
2004 "Make Babel instance command\n")
2006 vty
->node
= BABEL_NODE
;
2009 #endif /* HAVE_BABELD */
2012 DEFUNSH(VTYSH_OSPF6D
, router_ospf6
, router_ospf6_cmd
, "router ospf6 [vrf NAME]",
2013 ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR
)
2015 vty
->node
= OSPF6_NODE
;
2020 #if defined(HAVE_LDPD)
2021 DEFUNSH(VTYSH_LDPD
, ldp_mpls_ldp
, ldp_mpls_ldp_cmd
, "mpls ldp",
2022 "Global MPLS configuration subcommands\n"
2023 "Label Distribution Protocol\n")
2025 vty
->node
= LDP_NODE
;
2029 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv4
, ldp_address_family_ipv4_cmd
,
2030 "address-family ipv4",
2031 "Configure Address Family and its parameters\n"
2034 vty
->node
= LDP_IPV4_NODE
;
2038 DEFUNSH(VTYSH_LDPD
, ldp_address_family_ipv6
, ldp_address_family_ipv6_cmd
,
2039 "address-family ipv6",
2040 "Configure Address Family and its parameters\n"
2043 vty
->node
= LDP_IPV6_NODE
;
2047 DEFUNSH(VTYSH_LDPD
, ldp_exit_address_family
, ldp_exit_address_family_cmd
,
2048 "exit-address-family", "Exit from Address Family configuration mode\n")
2050 if (vty
->node
== LDP_IPV4_NODE
|| vty
->node
== LDP_IPV6_NODE
)
2051 vty
->node
= LDP_NODE
;
2055 DEFUNSH(VTYSH_LDPD
, ldp_interface_ifname
, ldp_interface_ifname_cmd
,
2057 "Enable LDP on an interface and enter interface submode\n"
2058 "Interface's name\n")
2060 switch (vty
->node
) {
2062 vty
->node
= LDP_IPV4_IFACE_NODE
;
2065 vty
->node
= LDP_IPV6_IFACE_NODE
;
2074 DEFUNSH(VTYSH_LDPD
, ldp_l2vpn_word_type_vpls
, ldp_l2vpn_word_type_vpls_cmd
,
2075 "l2vpn WORD type vpls",
2076 "Configure l2vpn commands\n"
2079 "Virtual Private LAN Service\n")
2081 vty
->node
= LDP_L2VPN_NODE
;
2085 DEFUNSH(VTYSH_LDPD
, ldp_member_pseudowire_ifname
,
2086 ldp_member_pseudowire_ifname_cmd
, "member pseudowire IFNAME",
2087 "L2VPN member configuration\n"
2088 "Pseudowire interface\n"
2089 "Interface's name\n")
2091 vty
->node
= LDP_PSEUDOWIRE_NODE
;
2097 DEFUNSH(VTYSH_ISISD
, router_isis
, router_isis_cmd
,
2098 "router isis WORD [vrf NAME]",
2101 "ISO Routing area tag\n" VRF_CMD_HELP_STR
)
2103 vty
->node
= ISIS_NODE
;
2106 #endif /* HAVE_ISISD */
2109 DEFUNSH(VTYSH_FABRICD
, router_openfabric
, router_openfabric_cmd
, "router openfabric WORD",
2111 "OpenFabric routing protocol\n"
2112 "ISO Routing area tag\n")
2114 vty
->node
= OPENFABRIC_NODE
;
2117 #endif /* HAVE_FABRICD */
2119 DEFUNSH(VTYSH_SR
, segment_routing
, segment_routing_cmd
,
2121 "Configure segment routing\n")
2123 vty
->node
= SEGMENT_ROUTING_NODE
;
2127 #if defined (HAVE_PATHD)
2128 DEFUNSH(VTYSH_PATHD
, sr_traffic_eng
, sr_traffic_eng_cmd
,
2130 "Configure SR traffic engineering\n")
2132 vty
->node
= SR_TRAFFIC_ENG_NODE
;
2136 DEFUNSH(VTYSH_PATHD
, srte_segment_list
, srte_segment_list_cmd
,
2137 "segment-list WORD$name",
2139 "Segment List Name\n")
2141 vty
->node
= SR_SEGMENT_LIST_NODE
;
2145 DEFUNSH(VTYSH_PATHD
, srte_policy
, srte_policy_cmd
,
2146 "policy color (0-4294967295) endpoint <A.B.C.D|X:X::X:X>",
2147 "Segment Routing Policy\n"
2149 "SR Policy color value\n"
2150 "SR Policy endpoint\n"
2151 "SR Policy endpoint IPv4 address\n"
2152 "SR Policy endpoint IPv6 address\n")
2154 vty
->node
= SR_POLICY_NODE
;
2158 DEFUNSH(VTYSH_PATHD
, srte_policy_candidate_dyn_path
,
2159 srte_policy_candidate_dyn_path_cmd
,
2160 "candidate-path preference (0-4294967295) name WORD dynamic",
2161 "Segment Routing Policy Candidate Path\n"
2162 "Segment Routing Policy Candidate Path Preference\n"
2163 "Administrative Preference\n"
2164 "Segment Routing Policy Candidate Path Name\n"
2168 vty
->node
= SR_CANDIDATE_DYN_NODE
;
2172 DEFUNSH(VTYSH_PATHD
, pcep
, pcep_cmd
,
2174 "Configure SR pcep\n")
2176 vty
->node
= PCEP_NODE
;
2180 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcc
, pcep_cli_pcc_cmd
,
2182 "PCC configuration\n")
2184 vty
->node
= PCEP_PCC_NODE
;
2188 DEFUNSH(VTYSH_PATHD
, pcep_cli_pce
, pcep_cli_pce_cmd
,
2190 "PCE configuration\n"
2193 vty
->node
= PCEP_PCE_NODE
;
2197 DEFUNSH(VTYSH_PATHD
, pcep_cli_pcep_pce_config
, pcep_cli_pcep_pce_config_cmd
,
2199 "PCEP peer Configuration Group\n"
2200 "PCEP peer Configuration Group name\n")
2202 vty
->node
= PCEP_PCE_CONFIG_NODE
;
2206 #endif /* HAVE_PATHD */
2208 /* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
2209 DEFUNSH(VTYSH_AFFMAP
, affinity_map
, vtysh_affinity_map_cmd
,
2210 "affinity-map NAME bit-position (0-1023)",
2211 "Affinity map configuration\n"
2212 "Affinity attribute name\n"
2213 "Bit position for affinity attribute value\n"
2219 /* max value is EXT_ADMIN_GROUP_MAX_POSITIONS - 1 */
2220 DEFUNSH(VTYSH_AFFMAP
, no_affinity_map
, vtysh_no_affinity_map_cmd
,
2221 "no affinity-map NAME$name [bit-position (0-1023)$position]",
2223 "Affinity map configuration\n"
2224 "Affinity attribute name\n"
2225 "Bit position for affinity attribute value\n"
2231 DEFUNSH(VTYSH_RMAP
, vtysh_route_map
, vtysh_route_map_cmd
,
2232 "route-map RMAP_NAME <deny|permit> (1-65535)",
2233 "Create route-map or enter route-map command mode\n"
2235 "Route map denies set operations\n"
2236 "Route map permits set operations\n"
2237 "Sequence to insert to/delete from existing route-map entry\n")
2239 vty
->node
= RMAP_NODE
;
2244 DEFUNSH(VTYSH_PBRD
, vtysh_pbr_map
, vtysh_pbr_map_cmd
,
2245 "pbr-map PBRMAP seq (1-700)",
2246 "Create pbr-map or enter pbr-map command mode\n"
2247 "The name of the PBR MAP\n"
2248 "Sequence to insert to/delete from existing pbr-map entry\n"
2249 "Sequence number\n")
2251 vty
->node
= PBRMAP_NODE
;
2255 DEFSH(VTYSH_PBRD
, vtysh_no_pbr_map_cmd
, "no pbr-map PBRMAP [seq (1-700)]",
2258 "The name of the PBR MAP\n"
2259 "Sequence to delete from existing pbr-map entry\n"
2260 "Sequence number\n")
2261 #endif /* HAVE_PBRD */
2264 DEFUNSH(VTYSH_BFDD
, bfd_enter
, bfd_enter_cmd
, "bfd", "Configure BFD peers\n")
2266 vty
->node
= BFD_NODE
;
2270 DEFUNSH(VTYSH_BFDD
, bfd_peer_enter
, bfd_peer_enter_cmd
,
2271 "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
2273 "IPv4 peer address\n"
2274 "IPv6 peer address\n"
2275 "Configure multihop\n"
2276 "Configure local address\n"
2277 "IPv4 local address\n"
2278 "IPv6 local address\n"
2280 "Configure interface name to use\n"
2282 "Configure VRF name\n")
2284 vty
->node
= BFD_PEER_NODE
;
2288 DEFUNSH(VTYSH_BFDD
, bfd_profile_enter
, bfd_profile_enter_cmd
,
2291 BFD_PROFILE_NAME_STR
)
2293 vty
->node
= BFD_PROFILE_NODE
;
2296 #endif /* HAVE_BFDD */
2298 DEFUNSH(VTYSH_ALL
, vtysh_line_vty
, vtysh_line_vty_cmd
, "line vty",
2299 "Configure a terminal line\n"
2300 "Virtual terminal\n")
2302 vty
->node
= VTY_NODE
;
2306 DEFUNSH(VTYSH_REALLYALL
, vtysh_enable
, vtysh_enable_cmd
, "enable",
2307 "Turn on privileged mode command\n")
2309 vty
->node
= ENABLE_NODE
;
2313 DEFUNSH(VTYSH_REALLYALL
, vtysh_disable
, vtysh_disable_cmd
, "disable",
2314 "Turn off privileged mode command\n")
2316 if (vty
->node
== ENABLE_NODE
)
2317 vty
->node
= VIEW_NODE
;
2321 DEFUNSH(VTYSH_REALLYALL
, vtysh_config_terminal
, vtysh_config_terminal_cmd
,
2322 "configure [terminal]",
2323 "Configuration from vty interface\n"
2324 "Configuration terminal\n")
2326 vty
->node
= CONFIG_NODE
;
2330 static int vtysh_exit(struct vty
*vty
)
2332 struct cmd_node
*cnode
= vector_lookup(cmdvec
, vty
->node
);
2334 if (vty
->node
== VIEW_NODE
|| vty
->node
== ENABLE_NODE
)
2336 if (cnode
->node_exit
)
2337 cnode
->node_exit(vty
);
2338 if (cnode
->parent_node
)
2339 vty
->node
= cnode
->parent_node
;
2341 if (vty
->node
== CONFIG_NODE
) {
2342 /* resync in case one of the daemons is somewhere else */
2343 vtysh_execute("end");
2344 vtysh_execute("configure");
2349 DEFUNSH(VTYSH_REALLYALL
, vtysh_exit_all
, vtysh_exit_all_cmd
, "exit",
2350 "Exit current mode and down to previous mode\n")
2352 return vtysh_exit(vty
);
2355 DEFUNSH(VTYSH_REALLYALL
, vtysh_quit_all
, vtysh_quit_all_cmd
, "quit",
2356 "Exit current mode and down to previous mode\n")
2358 return vtysh_exit_all(self
, vty
, argc
, argv
);
2362 DEFUNSH(VTYSH_BGPD
, exit_address_family
, exit_address_family_cmd
,
2363 "exit-address-family", "Exit from Address Family configuration mode\n")
2365 if (vty
->node
== BGP_IPV4_NODE
|| vty
->node
== BGP_IPV4M_NODE
2366 || vty
->node
== BGP_IPV4L_NODE
|| vty
->node
== BGP_VPNV4_NODE
2367 || vty
->node
== BGP_VPNV6_NODE
|| vty
->node
== BGP_IPV6_NODE
2368 || vty
->node
== BGP_IPV6L_NODE
|| vty
->node
== BGP_IPV6M_NODE
2369 || vty
->node
== BGP_EVPN_NODE
2370 || vty
->node
== BGP_FLOWSPECV4_NODE
2371 || vty
->node
== BGP_FLOWSPECV6_NODE
)
2372 vty
->node
= BGP_NODE
;
2376 DEFUNSH(VTYSH_BGPD
, exit_vni
, exit_vni_cmd
, "exit-vni", "Exit from VNI mode\n")
2378 if (vty
->node
== BGP_EVPN_VNI_NODE
)
2379 vty
->node
= BGP_EVPN_NODE
;
2383 DEFUNSH(VTYSH_BGPD
, rpki_exit
, rpki_exit_cmd
, "exit",
2384 "Exit current mode and down to previous mode\n")
2390 DEFUNSH(VTYSH_BGPD
, rpki_quit
, rpki_quit_cmd
, "quit",
2391 "Exit current mode and down to previous mode\n")
2393 return rpki_exit(self
, vty
, argc
, argv
);
2396 DEFUNSH(VTYSH_BGPD
, bmp_exit
, bmp_exit_cmd
, "exit",
2397 "Exit current mode and down to previous mode\n")
2403 DEFUNSH(VTYSH_BGPD
, bmp_quit
, bmp_quit_cmd
, "quit",
2404 "Exit current mode and down to previous mode\n")
2406 return bmp_exit(self
, vty
, argc
, argv
);
2408 #endif /* HAVE_BGPD */
2410 DEFUNSH(VTYSH_VRF
, exit_vrf_config
, exit_vrf_config_cmd
, "exit-vrf",
2411 "Exit from VRF configuration mode\n")
2413 if (vty
->node
== VRF_NODE
)
2414 vty
->node
= CONFIG_NODE
;
2418 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_config
, exit_srv6_config_cmd
, "exit",
2419 "Exit from SRv6 configuration mode\n")
2421 if (vty
->node
== SRV6_NODE
)
2422 vty
->node
= SEGMENT_ROUTING_NODE
;
2426 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_locs_config
, exit_srv6_locs_config_cmd
, "exit",
2427 "Exit from SRv6-locator configuration mode\n")
2429 if (vty
->node
== SRV6_LOCS_NODE
)
2430 vty
->node
= SRV6_NODE
;
2434 DEFUNSH(VTYSH_ZEBRA
, exit_srv6_loc_config
, exit_srv6_loc_config_cmd
, "exit",
2435 "Exit from SRv6-locators configuration mode\n")
2437 if (vty
->node
== SRV6_LOC_NODE
)
2438 vty
->node
= SRV6_LOCS_NODE
;
2443 DEFUNSH(VTYSH_RIPD
, vtysh_exit_ripd
, vtysh_exit_ripd_cmd
, "exit",
2444 "Exit current mode and down to previous mode\n")
2446 return vtysh_exit(vty
);
2449 DEFUNSH(VTYSH_RIPD
, vtysh_quit_ripd
, vtysh_quit_ripd_cmd
, "quit",
2450 "Exit current mode and down to previous mode\n")
2452 return vtysh_exit_ripd(self
, vty
, argc
, argv
);
2454 #endif /* HAVE_RIPD */
2457 DEFUNSH(VTYSH_RIPNGD
, vtysh_exit_ripngd
, vtysh_exit_ripngd_cmd
, "exit",
2458 "Exit current mode and down to previous mode\n")
2460 return vtysh_exit(vty
);
2463 DEFUNSH(VTYSH_RIPNGD
, vtysh_quit_ripngd
, vtysh_quit_ripngd_cmd
, "quit",
2464 "Exit current mode and down to previous mode\n")
2466 return vtysh_exit_ripngd(self
, vty
, argc
, argv
);
2468 #endif /* HAVE_RIPNGD */
2470 DEFUNSH(VTYSH_RMAP
, vtysh_exit_rmap
, vtysh_exit_rmap_cmd
, "exit",
2471 "Exit current mode and down to previous mode\n")
2473 return vtysh_exit(vty
);
2476 DEFUNSH(VTYSH_RMAP
, vtysh_quit_rmap
, vtysh_quit_rmap_cmd
, "quit",
2477 "Exit current mode and down to previous mode\n")
2479 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2483 DEFUNSH(VTYSH_PBRD
, vtysh_exit_pbr_map
, vtysh_exit_pbr_map_cmd
, "exit",
2484 "Exit current mode and down to previous mode\n")
2486 return vtysh_exit(vty
);
2489 DEFUNSH(VTYSH_PBRD
, vtysh_quit_pbr_map
, vtysh_quit_pbr_map_cmd
, "quit",
2490 "Exit current mode and down to previous mode\n")
2492 return vtysh_exit_rmap(self
, vty
, argc
, argv
);
2494 #endif /* HAVE_PBRD */
2497 DEFUNSH(VTYSH_BGPD
, vtysh_exit_bgpd
, vtysh_exit_bgpd_cmd
, "exit",
2498 "Exit current mode and down to previous mode\n")
2500 return vtysh_exit(vty
);
2503 DEFUNSH(VTYSH_BGPD
, vtysh_quit_bgpd
, vtysh_quit_bgpd_cmd
, "quit",
2504 "Exit current mode and down to previous mode\n")
2506 return vtysh_exit_bgpd(self
, vty
, argc
, argv
);
2508 #endif /* HAVE_BGPD */
2511 DEFUNSH(VTYSH_OSPFD
, vtysh_exit_ospfd
, vtysh_exit_ospfd_cmd
, "exit",
2512 "Exit current mode and down to previous mode\n")
2514 return vtysh_exit(vty
);
2517 DEFUNSH(VTYSH_OSPFD
, vtysh_quit_ospfd
, vtysh_quit_ospfd_cmd
, "quit",
2518 "Exit current mode and down to previous mode\n")
2520 return vtysh_exit_ospfd(self
, vty
, argc
, argv
);
2522 #endif /* HAVE_OSPFD */
2525 DEFUNSH(VTYSH_EIGRPD
, vtysh_exit_eigrpd
, vtysh_exit_eigrpd_cmd
, "exit",
2526 "Exit current mode and down to previous mode\n")
2528 return vtysh_exit(vty
);
2531 DEFUNSH(VTYSH_EIGRPD
, vtysh_quit_eigrpd
, vtysh_quit_eigrpd_cmd
, "quit",
2532 "Exit current mode and down to previous mode\n")
2534 return vtysh_exit(vty
);
2536 #endif /* HAVE_EIGRPD */
2539 DEFUNSH(VTYSH_BABELD
, vtysh_exit_babeld
, vtysh_exit_babeld_cmd
, "exit",
2540 "Exit current mode and down to previous mode\n")
2542 return vtysh_exit(vty
);
2545 DEFUNSH(VTYSH_BABELD
, vtysh_quit_babeld
, vtysh_quit_babeld_cmd
, "quit",
2546 "Exit current mode and down to previous mode\n")
2548 return vtysh_exit(vty
);
2550 #endif /* HAVE_BABELD */
2553 DEFUNSH(VTYSH_OSPF6D
, vtysh_exit_ospf6d
, vtysh_exit_ospf6d_cmd
, "exit",
2554 "Exit current mode and down to previous mode\n")
2556 return vtysh_exit(vty
);
2559 DEFUNSH(VTYSH_OSPF6D
, vtysh_quit_ospf6d
, vtysh_quit_ospf6d_cmd
, "quit",
2560 "Exit current mode and down to previous mode\n")
2562 return vtysh_exit_ospf6d(self
, vty
, argc
, argv
);
2564 #endif /* HAVE_OSPF6D */
2566 #if defined(HAVE_LDPD)
2567 DEFUNSH(VTYSH_LDPD
, vtysh_exit_ldpd
, vtysh_exit_ldpd_cmd
, "exit",
2568 "Exit current mode and down to previous mode\n")
2570 return vtysh_exit(vty
);
2573 ALIAS(vtysh_exit_ldpd
, vtysh_quit_ldpd_cmd
, "quit",
2574 "Exit current mode and down to previous mode\n")
2578 DEFUNSH(VTYSH_ISISD
, vtysh_exit_isisd
, vtysh_exit_isisd_cmd
, "exit",
2579 "Exit current mode and down to previous mode\n")
2581 return vtysh_exit(vty
);
2584 DEFUNSH(VTYSH_ISISD
, vtysh_quit_isisd
, vtysh_quit_isisd_cmd
, "quit",
2585 "Exit current mode and down to previous mode\n")
2587 return vtysh_exit_isisd(self
, vty
, argc
, argv
);
2589 #endif /* HAVE_ISISD */
2592 DEFUNSH(VTYSH_BFDD
, vtysh_exit_bfdd
, vtysh_exit_bfdd_cmd
, "exit",
2593 "Exit current mode and down to previous mode\n")
2595 return vtysh_exit(vty
);
2598 ALIAS(vtysh_exit_bfdd
, vtysh_quit_bfdd_cmd
, "quit",
2599 "Exit current mode and down to previous mode\n")
2603 DEFUNSH(VTYSH_FABRICD
, vtysh_exit_fabricd
, vtysh_exit_fabricd_cmd
, "exit",
2604 "Exit current mode and down to previous mode\n")
2606 return vtysh_exit(vty
);
2609 DEFUNSH(VTYSH_FABRICD
, vtysh_quit_fabricd
, vtysh_quit_fabricd_cmd
, "quit",
2610 "Exit current mode and down to previous mode\n")
2612 return vtysh_exit_fabricd(self
, vty
, argc
, argv
);
2614 #endif /* HAVE_FABRICD */
2616 DEFUNSH(VTYSH_KEYS
, vtysh_exit_keys
, vtysh_exit_keys_cmd
, "exit",
2617 "Exit current mode and down to previous mode\n")
2619 return vtysh_exit(vty
);
2622 DEFUNSH(VTYSH_KEYS
, vtysh_quit_keys
, vtysh_quit_keys_cmd
, "quit",
2623 "Exit current mode and down to previous mode\n")
2625 return vtysh_exit_keys(self
, vty
, argc
, argv
);
2628 DEFUNSH(VTYSH_SR
, vtysh_exit_sr
, vtysh_exit_sr_cmd
, "exit",
2629 "Exit current mode and down to previous mode\n")
2631 return vtysh_exit(vty
);
2634 DEFUNSH(VTYSH_SR
, vtysh_quit_sr
, vtysh_quit_sr_cmd
, "quit",
2635 "Exit current mode and down to previous mode\n")
2637 return vtysh_exit(vty
);
2640 #if defined(HAVE_PATHD)
2641 DEFUNSH(VTYSH_PATHD
, vtysh_exit_pathd
, vtysh_exit_pathd_cmd
, "exit",
2642 "Exit current mode and down to previous mode\n")
2644 return vtysh_exit(vty
);
2647 DEFUNSH(VTYSH_PATHD
, vtysh_quit_pathd
, vtysh_quit_pathd_cmd
, "quit",
2648 "Exit current mode and down to previous mode\n")
2650 return vtysh_exit_pathd(self
, vty
, argc
, argv
);
2652 #endif /* HAVE_PATHD */
2654 DEFUNSH(VTYSH_ALL
, vtysh_exit_line_vty
, vtysh_exit_line_vty_cmd
, "exit",
2655 "Exit current mode and down to previous mode\n")
2657 return vtysh_exit(vty
);
2660 DEFUNSH(VTYSH_ALL
, vtysh_quit_line_vty
, vtysh_quit_line_vty_cmd
, "quit",
2661 "Exit current mode and down to previous mode\n")
2663 return vtysh_exit_line_vty(self
, vty
, argc
, argv
);
2666 DEFUNSH(VTYSH_INTERFACE
, vtysh_interface
, vtysh_interface_cmd
,
2667 "interface IFNAME [vrf NAME]",
2668 "Select an interface to configure\n"
2669 "Interface's name\n" VRF_CMD_HELP_STR
)
2671 vty
->node
= INTERFACE_NODE
;
2675 DEFUNSH(VTYSH_ZEBRA
, vtysh_pseudowire
, vtysh_pseudowire_cmd
,
2676 "pseudowire IFNAME",
2677 "Static pseudowire configuration\n"
2678 "Pseudowire name\n")
2680 vty
->node
= PW_NODE
;
2684 DEFUNSH(VTYSH_NH_GROUP
,
2685 vtysh_nexthop_group
, vtysh_nexthop_group_cmd
,
2686 "nexthop-group NHGNAME",
2687 "Nexthop Group configuration\n"
2688 "Name of the Nexthop Group\n")
2690 vty
->node
= NH_GROUP_NODE
;
2694 DEFSH(VTYSH_NH_GROUP
, vtysh_no_nexthop_group_cmd
,
2695 "no nexthop-group NHGNAME",
2697 "Nexthop Group Configuration\n"
2698 "Name of the Nexthop Group\n")
2700 DEFUNSH(VTYSH_VRF
, vtysh_vrf
, vtysh_vrf_cmd
, "vrf NAME",
2701 "Select a VRF to configure\n"
2704 vty
->node
= VRF_NODE
;
2708 DEFUNSH(VTYSH_VRF
, vtysh_exit_vrf
, vtysh_exit_vrf_cmd
, "exit",
2709 "Exit current mode and down to previous mode\n")
2711 return vtysh_exit(vty
);
2714 DEFUNSH(VTYSH_VRF
, vtysh_quit_vrf
, vtysh_quit_vrf_cmd
, "quit",
2715 "Exit current mode and down to previous mode\n")
2717 return vtysh_exit_vrf(self
, vty
, argc
, argv
);
2720 DEFUNSH(VTYSH_NH_GROUP
,
2721 vtysh_exit_nexthop_group
, vtysh_exit_nexthop_group_cmd
,
2722 "exit", "Exit current mode and down to previous mode\n")
2724 return vtysh_exit(vty
);
2727 DEFUNSH(VTYSH_NH_GROUP
,
2728 vtysh_quit_nexthop_group
, vtysh_quit_nexthop_group_cmd
,
2729 "quit", "Exit current mode and down to previous mode\n")
2731 return vtysh_exit_nexthop_group(self
, vty
, argc
, argv
);
2734 DEFUNSH(VTYSH_INTERFACE
, vtysh_exit_interface
, vtysh_exit_interface_cmd
, "exit",
2735 "Exit current mode and down to previous mode\n")
2737 return vtysh_exit(vty
);
2740 DEFUNSH(VTYSH_INTERFACE
, vtysh_quit_interface
, vtysh_quit_interface_cmd
, "quit",
2741 "Exit current mode and down to previous mode\n")
2743 return vtysh_exit_interface(self
, vty
, argc
, argv
);
2746 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_pseudowire
, vtysh_exit_pseudowire_cmd
, "exit",
2747 "Exit current mode and down to previous mode\n")
2749 return vtysh_exit(vty
);
2752 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_pseudowire
, vtysh_quit_pseudowire_cmd
, "quit",
2753 "Exit current mode and down to previous mode\n")
2755 return vtysh_exit_pseudowire(self
, vty
, argc
, argv
);
2758 static char *do_prepend(struct vty
*vty
, struct cmd_token
**argv
, int argc
)
2760 const char *argstr
[argc
+ 1];
2763 if (vty
->node
!= VIEW_NODE
) {
2768 for (i
= 0; i
< argc
; i
++)
2769 argstr
[i
+ off
] = argv
[i
]->arg
;
2771 return frrstr_join(argstr
, argc
+ off
, " ");
2774 #pragma GCC diagnostic push
2775 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2776 /* 'headline' is a format string with a %s for the daemon name
2778 * Also for some reason GCC emits the warning on the end of the function
2779 * (optimization maybe?) rather than on the vty_out line, so this pragma
2780 * wraps the entire function rather than just the vty_out line.
2783 static int show_per_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2784 const char *headline
)
2787 int ret
= CMD_SUCCESS
;
2788 char *line
= do_prepend(vty
, argv
, argc
);
2790 for (i
= 0; i
< array_size(vtysh_client
); i
++)
2791 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
2792 vty_out(vty
, headline
, vtysh_client
[i
].name
);
2793 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
2797 XFREE(MTYPE_TMP
, line
);
2801 #pragma GCC diagnostic pop
2803 static int show_one_daemon(struct vty
*vty
, struct cmd_token
**argv
, int argc
,
2807 char *line
= do_prepend(vty
, argv
, argc
);
2809 ret
= vtysh_client_execute_name(name
, line
);
2811 XFREE(MTYPE_TMP
, line
);
2816 DEFUN (vtysh_show_thread_timer
,
2817 vtysh_show_thread_timer_cmd
,
2818 "show thread timers",
2820 "Thread information\n"
2821 "Show all timers and how long they have in the system\n")
2823 return show_per_daemon(vty
, argv
, argc
, "Thread timers for %s:\n");
2826 DEFUN (vtysh_show_poll
,
2827 vtysh_show_poll_cmd
,
2830 "Thread information\n"
2831 "Thread Poll Information\n")
2833 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2836 DEFUN (vtysh_show_thread
,
2837 vtysh_show_thread_cmd
,
2838 "show thread cpu [FILTER]",
2840 "Thread information\n"
2841 "Thread CPU usage\n"
2842 "Display filter (rwtexb)\n")
2844 return show_per_daemon(vty
, argv
, argc
, "Thread statistics for %s:\n");
2847 DEFUN (vtysh_show_work_queues
,
2848 vtysh_show_work_queues_cmd
,
2851 "Work Queue information\n")
2853 return show_per_daemon(vty
, argv
, argc
,
2854 "Work queue statistics for %s:\n");
2857 DEFUN (vtysh_show_work_queues_daemon
,
2858 vtysh_show_work_queues_daemon_cmd
,
2859 "show work-queues " DAEMONS_LIST
,
2861 "Work Queue information\n"
2864 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2867 DEFUNSH(VTYSH_ZEBRA
, vtysh_link_params
, vtysh_link_params_cmd
, "link-params",
2870 vty
->node
= LINK_PARAMS_NODE
;
2874 DEFUNSH(VTYSH_ZEBRA
, exit_link_params
, exit_link_params_cmd
, "exit-link-params",
2875 "Exit from Link Params configuration node\n")
2877 if (vty
->node
== LINK_PARAMS_NODE
)
2878 vty
->node
= INTERFACE_NODE
;
2882 DEFUNSH(VTYSH_ZEBRA
, vtysh_exit_link_params
, vtysh_exit_link_params_cmd
, "exit",
2883 "Exit current mode and down to previous mode\n")
2885 if (vty
->node
== LINK_PARAMS_NODE
)
2886 vty
->node
= INTERFACE_NODE
;
2890 DEFUNSH(VTYSH_ZEBRA
, vtysh_quit_link_params
, vtysh_quit_link_params_cmd
, "quit",
2891 "Exit current mode and down to previous mode\n")
2893 return vtysh_exit_link_params(self
, vty
, argc
, argv
);
2896 DEFUNSH_HIDDEN (0x00,
2898 vtysh_debug_all_cmd
,
2902 "Toggle all debugs on or off\n")
2907 DEFUN (vtysh_show_debugging
,
2908 vtysh_show_debugging_cmd
,
2913 return show_per_daemon(vty
, argv
, argc
, "");
2916 DEFUN (vtysh_show_debugging_hashtable
,
2917 vtysh_show_debugging_hashtable_cmd
,
2918 "show debugging hashtable [statistics]",
2921 "Statistics about hash tables\n"
2922 "Statistics about hash tables\n")
2924 bool stats
= strmatch(argv
[argc
- 1]->text
, "statistics");
2928 "Load factor (LF) - average number of elements across all buckets\n");
2930 "Full load factor (FLF) - average number of elements across full buckets\n\n");
2932 "Standard deviation (SD) is calculated for both the LF and FLF\n");
2934 "and indicates the typical deviation of bucket chain length\n");
2935 vty_out(vty
, "from the value in the corresponding load factor.\n\n");
2937 return show_per_daemon(vty
, argv
, stats
? argc
- 1 : argc
,
2938 "Hashtable statistics for %s:\n");
2941 DEFUN (vtysh_show_error_code
,
2942 vtysh_show_error_code_cmd
,
2943 "show error <(1-4294967296)|all> [json]",
2945 "Information on errors\n"
2946 "Error code to get info about\n"
2947 "Information on all errors\n"
2952 if (!strmatch(argv
[2]->text
, "all"))
2953 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2955 /* If it's not a shared code, send it to all the daemons */
2956 if (arg
< LIB_FERR_START
|| arg
> LIB_FERR_END
) {
2957 show_per_daemon(vty
, argv
, argc
, "");
2958 /* Otherwise, print it ourselves to avoid duplication */
2960 bool json
= strmatch(argv
[argc
- 1]->text
, "json");
2962 if (!strmatch(argv
[2]->text
, "all"))
2963 arg
= strtoul(argv
[2]->arg
, NULL
, 10);
2965 log_ref_display(vty
, arg
, json
);
2972 DEFUN_HIDDEN (show_config_running
,
2973 show_config_running_cmd
,
2974 "show configuration running\
2975 [<json|xml> [translate WORD]]\
2976 [with-defaults] " DAEMONS_LIST
,
2978 "Configuration information\n"
2979 "Running configuration\n"
2980 "Change output format to JSON\n"
2981 "Change output format to XML\n"
2982 "Translate output\n"
2983 "YANG module translator\n"
2984 "Show default values\n"
2987 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
2990 DEFUN (show_yang_operational_data
,
2991 show_yang_operational_data_cmd
,
2992 "show yang operational-data XPATH\
2999 "YANG information\n"
3000 "Show YANG operational data\n"
3001 "XPath expression specifying the YANG data path\n"
3002 "Set the output format\n"
3003 "JavaScript Object Notation\n"
3004 "Extensible Markup Language\n"
3005 "Translate operational data\n"
3006 "YANG module translator\n"
3007 "Merge configuration data\n"
3010 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3013 DEFUN(show_yang_module
, show_yang_module_cmd
,
3014 "show yang module [module-translator WORD] " DAEMONS_LIST
,
3016 "YANG information\n"
3017 "Show loaded modules\n"
3018 "YANG module translator\n"
3019 "YANG module translator\n" DAEMONS_STR
)
3021 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3024 DEFUN(show_yang_module_detail
, show_yang_module_detail_cmd
,
3026 [module-translator WORD]\
3027 WORD <compiled|summary|tree|yang|yin> " DAEMONS_LIST
,
3029 "YANG information\n"
3030 "Show loaded modules\n"
3031 "YANG module translator\n"
3032 "YANG module translator\n"
3034 "Display compiled module in YANG format\n"
3035 "Display summary information about the module\n"
3036 "Display module in the tree (RFC 8340) format\n"
3037 "Display module in the YANG format\n"
3038 "Display module in the YIN format\n" DAEMONS_STR
)
3040 return show_one_daemon(vty
, argv
, argc
- 1, argv
[argc
- 1]->text
);
3044 DEFUNSH(VTYSH_ALL
, debug_nb
,
3046 "[no] debug northbound\
3048 callbacks [{configuration|state|rpc}]\
3055 "Northbound debugging\n"
3062 "libyang debugging\n")
3067 DEFUN (vtysh_show_history
,
3068 vtysh_show_history_cmd
,
3071 "The list of commands stored in history\n")
3073 HIST_ENTRY
**hlist
= history_list();
3077 vty_out(vty
, "%s\n", hlist
[i
]->line
);
3084 DEFUN (vtysh_show_memory
,
3085 vtysh_show_memory_cmd
,
3086 "show memory [" DAEMONS_LIST
"]",
3088 "Memory statistics\n"
3092 return show_one_daemon(vty
, argv
, argc
- 1,
3093 argv
[argc
- 1]->text
);
3095 return show_per_daemon(vty
, argv
, argc
, "Memory statistics for %s:\n");
3098 DEFUN (vtysh_show_modules
,
3099 vtysh_show_modules_cmd
,
3104 return show_per_daemon(vty
, argv
, argc
, "Module information for %s:\n");
3107 /* Logging commands. */
3108 DEFUN (vtysh_show_logging
,
3109 vtysh_show_logging_cmd
,
3112 "Show current logging configuration\n")
3114 return show_per_daemon(vty
, argv
, argc
,
3115 "Logging configuration for %s:\n");
3118 DEFUNSH(VTYSH_ALL
, vtysh_debug_memstats
,
3119 vtysh_debug_memstats_cmd
, "[no] debug memstats-at-exit",
3122 "Print memory statistics at exit\n")
3127 DEFUN(vtysh_debug_uid_backtrace
,
3128 vtysh_debug_uid_backtrace_cmd
,
3129 "[no] debug unique-id UID backtrace",
3132 "Options per individual log message, by unique ID\n"
3133 "Log message unique ID (XXXXX-XXXXX)\n"
3134 "Add backtrace to log when message is printed\n")
3136 unsigned int i
, ok
= 0;
3137 int err
= CMD_SUCCESS
, ret
;
3141 if (!strcmp(argv
[0]->text
, "no")) {
3143 snprintfrr(line
, sizeof(line
),
3144 "no debug unique-id %s backtrace", uid
);
3147 snprintfrr(line
, sizeof(line
), "debug unique-id %s backtrace",
3151 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3152 if (vtysh_client
[i
].fd
>= 0 || vtysh_client
[i
].next
) {
3153 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3158 case CMD_ERR_NOTHING_TODO
:
3159 /* ignore this daemon
3161 * note this doesn't need to handle instances
3162 * of the same daemon individually because
3163 * the same daemon will have the same UIDs
3167 if (err
== CMD_SUCCESS
)
3173 if (err
== CMD_SUCCESS
&& !ok
) {
3174 vty_out(vty
, "%% no running daemon recognizes unique-ID %s\n",
3181 DEFUNSH(VTYSH_ALL
, vtysh_allow_reserved_ranges
, vtysh_allow_reserved_ranges_cmd
,
3182 "allow-reserved-ranges",
3183 "Allow using IPv4 (Class E) reserved IP space\n")
3188 DEFUNSH(VTYSH_ALL
, no_vtysh_allow_reserved_ranges
,
3189 no_vtysh_allow_reserved_ranges_cmd
, "no allow-reserved-ranges",
3190 NO_STR
"Allow using IPv4 (Class E) reserved IP space\n")
3195 DEFUNSH(VTYSH_ALL
, vtysh_service_password_encrypt
,
3196 vtysh_service_password_encrypt_cmd
, "service password-encryption",
3197 "Set up miscellaneous service\n"
3198 "Enable encrypted passwords\n")
3203 DEFUNSH(VTYSH_ALL
, no_vtysh_service_password_encrypt
,
3204 no_vtysh_service_password_encrypt_cmd
, "no service password-encryption",
3206 "Set up miscellaneous service\n"
3207 "Enable encrypted passwords\n")
3212 DEFUNSH(VTYSH_ALL
, vtysh_config_password
, vtysh_password_cmd
,
3213 "password [(8-8)] LINE",
3214 "Modify the terminal connection password\n"
3215 "Specifies a HIDDEN password will follow\n"
3216 "The password string\n")
3221 DEFUNSH(VTYSH_ALL
, no_vtysh_config_password
, no_vtysh_password_cmd
,
3222 "no password", NO_STR
3223 "Modify the terminal connection password\n")
3225 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3230 DEFUNSH(VTYSH_ALL
, vtysh_config_enable_password
, vtysh_enable_password_cmd
,
3231 "enable password [(8-8)] LINE",
3232 "Modify enable password parameters\n"
3233 "Assign the privileged level password\n"
3234 "Specifies a HIDDEN password will follow\n"
3235 "The 'enable' password string\n")
3240 DEFUNSH(VTYSH_ALL
, no_vtysh_config_enable_password
,
3241 no_vtysh_enable_password_cmd
, "no enable password", NO_STR
3242 "Modify enable password parameters\n"
3243 "Assign the privileged level password\n")
3245 vty_out(vty
, NO_PASSWD_CMD_WARNING
);
3250 DEFUN (vtysh_write_terminal
,
3251 vtysh_write_terminal_cmd
,
3252 "write terminal ["DAEMONS_LIST
"] [no-header]",
3253 "Write running configuration to memory, network, or terminal\n"
3254 "Write to terminal\n"
3256 "Skip \"Building configuration...\" header\n")
3259 char line
[] = "do write terminal";
3261 if (!strcmp(argv
[argc
- 1]->arg
, "no-header"))
3264 vty_out(vty
, "Building configuration...\n");
3265 vty_out(vty
, "\nCurrent configuration:\n");
3266 vty_out(vty
, "!\n");
3269 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3271 || (strmatch(vtysh_client
[i
].name
, argv
[2]->text
)))
3272 vtysh_client_config(&vtysh_client
[i
], line
);
3274 /* Integrate vtysh specific configuration. */
3275 vty_open_pager(vty
);
3276 vtysh_config_write();
3277 vtysh_config_dump();
3278 vty_close_pager(vty
);
3279 vty_out(vty
, "end\n");
3284 DEFUN (vtysh_show_running_config
,
3285 vtysh_show_running_config_cmd
,
3286 "show running-config ["DAEMONS_LIST
"] [no-header]",
3288 "Current operating configuration\n"
3290 "Skip \"Building configuration...\" header\n")
3292 return vtysh_write_terminal(self
, vty
, argc
, argv
);
3295 DEFUN (vtysh_integrated_config
,
3296 vtysh_integrated_config_cmd
,
3297 "service integrated-vtysh-config",
3298 "Set up miscellaneous service\n"
3299 "Write configuration into integrated file\n")
3301 vtysh_write_integrated
= WRITE_INTEGRATED_YES
;
3305 DEFUN (no_vtysh_integrated_config
,
3306 no_vtysh_integrated_config_cmd
,
3307 "no service integrated-vtysh-config",
3309 "Set up miscellaneous service\n"
3310 "Write configuration into integrated file\n")
3312 vtysh_write_integrated
= WRITE_INTEGRATED_NO
;
3316 static void backup_config_file(const char *fbackup
)
3318 char *integrate_sav
= NULL
;
3320 size_t integrate_sav_sz
= strlen(fbackup
) + strlen(CONF_BACKUP_EXT
) + 1;
3321 integrate_sav
= malloc(integrate_sav_sz
);
3322 strlcpy(integrate_sav
, fbackup
, integrate_sav_sz
);
3323 strlcat(integrate_sav
, CONF_BACKUP_EXT
, integrate_sav_sz
);
3325 /* Move current configuration file to backup config file. */
3326 if (unlink(integrate_sav
) != 0 && errno
!= ENOENT
)
3327 vty_out(vty
, "Unlink failed for %s: %s\n", integrate_sav
,
3329 if (rename(fbackup
, integrate_sav
) != 0 && errno
!= ENOENT
)
3330 vty_out(vty
, "Error renaming %s to %s: %s\n", fbackup
,
3331 integrate_sav
, strerror(errno
));
3332 free(integrate_sav
);
3335 int vtysh_write_config_integrated(void)
3338 char line
[] = "do write terminal";
3342 struct passwd
*pwentry
;
3345 struct group
*grentry
;
3352 vty_out(vty
, "Building Configuration...\n");
3354 backup_config_file(frr_config
);
3355 fp
= fopen(frr_config
, "w");
3358 "%% Error: failed to open configuration file %s: %s\n",
3359 frr_config
, safe_strerror(errno
));
3360 return CMD_WARNING_CONFIG_FAILED
;
3364 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3365 vtysh_client_config(&vtysh_client
[i
], line
);
3367 vtysh_config_write();
3368 vty
->of_saved
= vty
->of
;
3370 vtysh_config_dump();
3371 vty
->of
= vty
->of_saved
;
3373 if (fchmod(fd
, CONFIGFILE_MASK
) != 0) {
3374 printf("%% Warning: can't chmod configuration file %s: %s\n",
3375 frr_config
, safe_strerror(errno
));
3380 pwentry
= getpwnam(FRR_USER
);
3382 uid
= pwentry
->pw_uid
;
3384 printf("%% Warning: could not look up user \"%s\"\n", FRR_USER
);
3389 grentry
= getgrnam(FRR_GROUP
);
3391 gid
= grentry
->gr_gid
;
3393 printf("%% Warning: could not look up group \"%s\"\n",
3399 if (!fstat(fd
, &st
)) {
3400 if (st
.st_uid
== uid
)
3402 if (st
.st_gid
== gid
)
3404 if ((uid
!= (uid_t
)-1 || gid
!= (gid_t
)-1)
3405 && fchown(fd
, uid
, gid
)) {
3406 printf("%% Warning: can't chown configuration file %s: %s\n",
3407 frr_config
, safe_strerror(errno
));
3411 printf("%% Warning: stat() failed on %s: %s\n", frr_config
,
3412 safe_strerror(errno
));
3416 if (fflush(fp
) != 0) {
3417 printf("%% Warning: fflush() failed on %s: %s\n", frr_config
,
3418 safe_strerror(errno
));
3422 if (fsync(fd
) < 0) {
3423 printf("%% Warning: fsync() failed on %s: %s\n", frr_config
,
3424 safe_strerror(errno
));
3430 printf("Integrated configuration saved to %s\n", frr_config
);
3438 DEFUN_HIDDEN(start_config
, start_config_cmd
, "XFRR_start_configuration",
3439 "The Beginning of Configuration\n")
3442 char line
[] = "XFRR_start_configuration";
3444 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3445 vtysh_client_execute(&vtysh_client
[i
], line
);
3450 DEFUN_HIDDEN(end_config
, end_config_cmd
, "XFRR_end_configuration",
3451 "The End of Configuration\n")
3454 char line
[] = "XFRR_end_configuration";
3456 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3457 vtysh_client_execute(&vtysh_client
[i
], line
);
3462 static bool want_config_integrated(void)
3466 switch (vtysh_write_integrated
) {
3467 case WRITE_INTEGRATED_UNSPECIFIED
:
3468 if (stat(frr_config
, &s
) && errno
== ENOENT
)
3471 case WRITE_INTEGRATED_NO
:
3473 case WRITE_INTEGRATED_YES
:
3479 DEFUN (vtysh_write_memory
,
3480 vtysh_write_memory_cmd
,
3481 "write [<memory|file>]",
3482 "Write running configuration to memory, network, or terminal\n"
3483 "Write configuration to the file (same as write file)\n"
3484 "Write configuration to the file (same as write memory)\n")
3486 int ret
= CMD_SUCCESS
;
3487 char line
[] = "do write memory";
3490 vty_out(vty
, "Note: this version of vtysh never writes vtysh.conf\n");
3492 /* If integrated frr.conf explicitly set. */
3493 if (want_config_integrated()) {
3494 ret
= CMD_WARNING_CONFIG_FAILED
;
3496 /* first attempt to use watchfrr if it's available */
3497 bool used_watchfrr
= false;
3499 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3500 if (vtysh_client
[i
].flag
== VTYSH_WATCHFRR
)
3502 if (i
< array_size(vtysh_client
) && vtysh_client
[i
].fd
!= -1) {
3503 used_watchfrr
= true;
3504 ret
= vtysh_client_execute(&vtysh_client
[i
],
3505 "do write integrated");
3509 * If we didn't use watchfrr, fallback to writing the config
3512 if (!used_watchfrr
) {
3513 printf("\nWarning: attempting direct configuration write without watchfrr.\nFile permissions and ownership may be incorrect, or write may fail.\n\n");
3514 ret
= vtysh_write_config_integrated();
3519 vty_out(vty
, "Building Configuration...\n");
3521 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3522 ret
= vtysh_client_execute(&vtysh_client
[i
], line
);
3527 DEFUN (vtysh_copy_running_config
,
3528 vtysh_copy_running_config_cmd
,
3529 "copy running-config startup-config",
3530 "Copy from one file to another\n"
3531 "Copy from current system configuration\n"
3532 "Copy to startup configuration\n")
3534 return vtysh_write_memory(self
, vty
, argc
, argv
);
3537 DEFUN (vtysh_copy_to_running
,
3538 vtysh_copy_to_running_cmd
,
3539 "copy FILENAME running-config",
3540 "Apply a configuration file\n"
3541 "Configuration file to read\n"
3542 "Apply to current configuration\n")
3545 const char *fname
= argv
[1]->arg
;
3547 ret
= vtysh_read_config(fname
, true);
3549 /* Return to enable mode - the 'read_config' api leaves us up a level */
3550 vtysh_execute_no_pager("enable");
3555 DEFUN (vtysh_terminal_paginate
,
3556 vtysh_terminal_paginate_cmd
,
3557 "[no] terminal paginate",
3559 "Set terminal line parameters\n"
3560 "Use pager for output scrolling\n")
3562 free(vtysh_pager_name
);
3563 vtysh_pager_name
= NULL
;
3565 if (strcmp(argv
[0]->text
, "no"))
3566 vtysh_pager_envdef(true);
3570 DEFUN (vtysh_terminal_length
,
3571 vtysh_terminal_length_cmd
,
3572 "[no] terminal length (0-4294967295)",
3574 "Set terminal line parameters\n"
3575 "Set number of lines on a screen\n"
3576 "Number of lines on screen (0 for no pausing, nonzero to use pager)\n")
3579 unsigned long lines
;
3581 free(vtysh_pager_name
);
3582 vtysh_pager_name
= NULL
;
3584 if (!strcmp(argv
[0]->text
, "no") || !strcmp(argv
[1]->text
, "no")) {
3585 /* "terminal no length" = use VTYSH_PAGER */
3586 vtysh_pager_envdef(true);
3590 lines
= strtoul(argv
[idx_number
]->arg
, NULL
, 10);
3593 "%% The \"terminal length\" command is deprecated and its value is ignored.\n"
3594 "%% Please use \"terminal paginate\" instead with OS TTY length handling.\n");
3595 vtysh_pager_envdef(true);
3601 ALIAS_DEPRECATED(vtysh_terminal_length
,
3602 vtysh_terminal_no_length_cmd
,
3603 "terminal no length",
3604 "Set terminal line parameters\n"
3606 "Set number of lines on a screen\n")
3608 DEFUN (vtysh_show_daemons
,
3609 vtysh_show_daemons_cmd
,
3612 "Show list of running daemons\n")
3616 for (i
= 0; i
< array_size(vtysh_client
); i
++)
3617 if (vtysh_client
[i
].fd
>= 0)
3618 vty_out(vty
, " %s", vtysh_client
[i
].name
);
3624 struct visual_prio
{
3625 /* 4 characters for nice alignment */
3628 int c256_background
;
3632 /* clang-format off */
3633 struct visual_prio visual_prios
[] = {
3635 .label
= "\e[31;1mEMRG",
3636 .c256_background
= 53,
3637 .c256_formatarg
= 225,
3640 .label
= "\e[31;1mALRT",
3641 .c256_background
= 53,
3642 .c256_formatarg
= 225,
3645 .label
= "\e[31;1mCRIT",
3646 .c256_background
= 53,
3647 .c256_formatarg
= 225,
3650 .label
= "\e[38;5;202mERR!",
3651 .c256_background
= 52,
3652 .c256_formatarg
= 224,
3655 .label
= "\e[38;5;222mWARN",
3656 .c256_background
= 58,
3657 .c256_formatarg
= 230,
3661 .c256_background
= 234,
3662 .c256_formatarg
= 195,
3665 .label
= "\e[38;5;192mINFO",
3666 .c256_background
= 236,
3667 .c256_formatarg
= 195,
3670 .label
= "\e[38;5;116mDEBG",
3671 .c256_background
= 238,
3672 .c256_formatarg
= 195,
3675 /* clang-format on */
3677 static void vtysh_log_print(struct vtysh_client
*vclient
,
3678 struct zlog_live_hdr
*hdr
, const char *text
)
3680 size_t textlen
= hdr
->textlen
, textpos
= 0;
3681 time_t ts
= hdr
->ts_sec
;
3682 struct visual_prio
*vis
;
3686 if (hdr
->prio
>= array_size(visual_prios
))
3687 vis
= &visual_prios
[LOG_CRIT
];
3689 vis
= &visual_prios
[hdr
->prio
];
3691 localtime_r(&ts
, &tm
);
3692 strftime(ts_buf
, sizeof(ts_buf
), "%Y-%m-%d %H:%M:%S", &tm
);
3695 const char *label
= vis
->label
+ strlen(vis
->label
) - 4;
3697 fprintf(stderr
, "%s.%03u [%s] %s: %.*s\n", ts_buf
,
3698 hdr
->ts_nsec
/ 1000000U, label
, vclient
->name
,
3699 (int)textlen
, text
);
3704 "\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",
3705 vis
->c256_background
, ts_buf
, hdr
->ts_nsec
/ 1000000U,
3706 vis
->label
, vclient
->name
);
3708 for (size_t fmtpos
= 0; fmtpos
< hdr
->n_argpos
; fmtpos
++) {
3709 struct fmt_outpos
*fmt
= &hdr
->argpos
[fmtpos
];
3711 if (fmt
->off_start
< textpos
|| fmt
->off_end
< fmt
->off_start
||
3712 fmt
->off_end
> textlen
)
3715 while (fmt
->off_end
> fmt
->off_start
&&
3716 text
[fmt
->off_end
- 1] == ' ')
3719 fprintf(stderr
, "%.*s\e[38;5;%dm%.*s\e[38;5;251m",
3720 (int)(fmt
->off_start
- textpos
), text
+ textpos
,
3721 vis
->c256_formatarg
,
3722 (int)(fmt
->off_end
- fmt
->off_start
),
3723 text
+ fmt
->off_start
);
3724 textpos
= fmt
->off_end
;
3726 fprintf(stderr
, "%.*s\033[K\033[m\n", (int)(textlen
- textpos
),
3730 static void vtysh_log_read(struct thread
*thread
)
3732 struct vtysh_client
*vclient
= THREAD_ARG(thread
);
3734 struct zlog_live_hdr hdr
;
3740 thread_add_read(master
, vtysh_log_read
, vclient
, vclient
->log_fd
,
3741 &vclient
->log_reader
);
3743 ret
= recv(vclient
->log_fd
, &buf
, sizeof(buf
), 0);
3745 if (ret
< 0 && ERRNO_IO_RETRY(errno
))
3748 if (stderr_stdout_same
) {
3749 #ifdef HAVE_RL_CLEAR_VISIBLE_LINE
3750 rl_clear_visible_line();
3760 buf
.text
[0] = '\0'; /* coverity */
3763 snprintfrr(buf
.text
, sizeof(buf
.text
),
3764 "log monitor connection error: %m");
3767 buf
.text
, sizeof(buf
.text
),
3768 "log monitor connection closed unexpectedly");
3769 buf
.hdr
.textlen
= strlen(buf
.text
);
3771 THREAD_OFF(vclient
->log_reader
);
3772 close(vclient
->log_fd
);
3773 vclient
->log_fd
= -1;
3775 clock_gettime(CLOCK_REALTIME
, &ts
);
3776 buf
.hdr
.ts_sec
= ts
.tv_sec
;
3777 buf
.hdr
.ts_nsec
= ts
.tv_nsec
;
3778 buf
.hdr
.prio
= LOG_ERR
;
3780 buf
.hdr
.texthdrlen
= 0;
3781 buf
.hdr
.n_argpos
= 0;
3783 int32_t lost_msgs
= buf
.hdr
.lost_msgs
- vclient
->lost_msgs
;
3785 if (lost_msgs
> 0) {
3786 vclient
->lost_msgs
= buf
.hdr
.lost_msgs
;
3788 "%d log messages from %s lost (vtysh reading too slowly)\n",
3789 lost_msgs
, vclient
->name
);
3793 text
= buf
.text
+ sizeof(buf
.hdr
.argpos
[0]) * buf
.hdr
.n_argpos
;
3794 vtysh_log_print(vclient
, &buf
.hdr
, text
);
3796 if (stderr_stdout_same
)
3797 rl_forced_update_display();
3803 /* clippy/clidef can't process the DEFPY below without some value for this */
3804 #define DAEMONS_LIST "daemon"
3807 DEFPY (vtysh_terminal_monitor
,
3808 vtysh_terminal_monitor_cmd
,
3809 "terminal monitor ["DAEMONS_LIST
"]$daemon",
3810 "Set terminal line parameters\n"
3811 "Receive log messages to active VTY session\n"
3814 static const char line
[] = "terminal monitor";
3815 int ret_all
= CMD_SUCCESS
, ret
, fd
;
3818 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3819 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3821 if (daemon
&& strcmp(vclient
->name
, daemon
))
3824 for (; vclient
; vclient
= vclient
->next
) {
3825 if (vclient
->log_fd
!= -1) {
3826 vty_out(vty
, "%% %s: already monitoring logs\n",
3833 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, &fd
);
3835 set_nonblocking(fd
);
3836 vclient
->log_fd
= fd
;
3837 thread_add_read(master
, vtysh_log_read
, vclient
,
3839 &vclient
->log_reader
);
3841 if (ret
!= CMD_SUCCESS
) {
3842 vty_out(vty
, "%% failed to enable logs on %s\n",
3844 ret_all
= CMD_WARNING
;
3850 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3852 "%% command had no effect, relevant daemons not connected?\n");
3853 ret_all
= CMD_WARNING
;
3858 DEFPY (no_vtysh_terminal_monitor
,
3859 no_vtysh_terminal_monitor_cmd
,
3860 "no terminal monitor ["DAEMONS_LIST
"]$daemon",
3862 "Set terminal line parameters\n"
3863 "Receive log messages to active VTY session\n"
3866 static const char line
[] = "no terminal monitor";
3867 int ret_all
= CMD_SUCCESS
, ret
;
3870 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
3871 struct vtysh_client
*vclient
= &vtysh_client
[i
];
3873 if (daemon
&& strcmp(vclient
->name
, daemon
))
3876 for (; vclient
; vclient
= vclient
->next
) {
3877 /* run this even if log_fd == -1, in case something
3880 ret
= vtysh_client_run(vclient
, line
, NULL
, NULL
, NULL
);
3881 if (ret
!= CMD_SUCCESS
) {
3883 "%% failed to disable logs on %s\n",
3885 ret_all
= CMD_WARNING
;
3889 /* with this being a datagram socket, we can't expect
3890 * a close notification...
3892 if (vclient
->log_fd
!= -1) {
3893 THREAD_OFF(vclient
->log_reader
);
3895 close(vclient
->log_fd
);
3896 vclient
->log_fd
= -1;
3901 if (!ok
&& ret_all
== CMD_SUCCESS
) {
3903 "%% command had no effect, relevant daemons not connected?\n");
3904 ret_all
= CMD_WARNING
;
3910 /* Execute command in child process. */
3911 static void execute_command(const char *command
, int argc
, const char *arg1
,
3921 /* Failure of fork(). */
3922 fprintf(stderr
, "Can't fork: %s\n", safe_strerror(errno
));
3924 } else if (pid
== 0) {
3925 /* This is child process. */
3928 execlp(command
, command
, (const char *)NULL
);
3931 execlp(command
, command
, arg1
, (const char *)NULL
);
3934 execlp(command
, command
, arg1
, arg2
,
3935 (const char *)NULL
);
3939 /* When execlp suceed, this part is not executed. */
3940 fprintf(stderr
, "Can't execute %s: %s\n", command
,
3941 safe_strerror(errno
));
3944 /* This is parent. */
3946 wait4(pid
, &status
, 0, NULL
);
3954 "Send echo messages\n"
3955 "Ping destination address or hostname\n")
3959 argv_find(argv
, argc
, "WORD", &idx
);
3960 execute_command("ping", 1, argv
[idx
]->arg
, NULL
);
3964 DEFUN(vtysh_motd
, vtysh_motd_cmd
, "show motd", SHOW_STR
"Show motd\n")
3970 ALIAS(vtysh_ping
, vtysh_ping_ip_cmd
, "ping ip WORD",
3971 "Send echo messages\n"
3973 "Ping destination address or hostname\n")
3975 DEFUN (vtysh_traceroute
,
3976 vtysh_traceroute_cmd
,
3978 "Trace route to destination\n"
3979 "Trace route to destination address or hostname\n")
3983 argv_find(argv
, argc
, "WORD", &idx
);
3984 execute_command("traceroute", 1, argv
[idx
]->arg
, NULL
);
3988 ALIAS(vtysh_traceroute
, vtysh_traceroute_ip_cmd
, "traceroute ip WORD",
3989 "Trace route to destination\n"
3991 "Trace route to destination address or hostname\n")
3993 DEFUN (vtysh_mtrace
,
3995 "mtrace WORD [WORD]",
3996 "Multicast trace route to multicast source\n"
3997 "Multicast trace route to multicast source address\n"
3998 "Multicast trace route for multicast group address\n")
4001 execute_command("mtracebis", 1, argv
[1]->arg
, NULL
);
4003 execute_command("mtracebis", 2, argv
[1]->arg
, argv
[2]->arg
);
4010 "Send echo messages\n"
4012 "Ping destination address or hostname\n")
4014 execute_command("ping6", 1, argv
[2]->arg
, NULL
);
4018 DEFUN (vtysh_traceroute6
,
4019 vtysh_traceroute6_cmd
,
4020 "traceroute ipv6 WORD",
4021 "Trace route to destination\n"
4023 "Trace route to destination address or hostname\n")
4025 execute_command("traceroute6", 1, argv
[2]->arg
, NULL
);
4029 #if CONFDATE > 20240201
4030 CPP_NOTICE("Remove HAVE_SHELL_ACCESS and it's documentation");
4032 #if defined(HAVE_SHELL_ACCESS)
4033 DEFUN (vtysh_telnet
,
4036 "Open a telnet connection\n"
4037 "IP address or hostname of a remote system\n")
4039 execute_command("telnet", 1, argv
[1]->arg
, NULL
);
4043 DEFUN (vtysh_telnet_port
,
4044 vtysh_telnet_port_cmd
,
4046 "Open a telnet connection\n"
4047 "IP address or hostname of a remote system\n"
4048 "TCP Port number\n")
4050 execute_command("telnet", 2, argv
[1]->arg
, argv
[2]->arg
);
4057 "Open an ssh connection\n"
4060 execute_command("ssh", 1, argv
[1]->arg
, NULL
);
4064 DEFUN (vtysh_start_shell
,
4065 vtysh_start_shell_cmd
,
4067 "Start UNIX shell\n")
4069 execute_command("sh", 0, NULL
, NULL
);
4073 DEFUN (vtysh_start_bash
,
4074 vtysh_start_bash_cmd
,
4076 "Start UNIX shell\n"
4079 execute_command("bash", 0, NULL
, NULL
);
4083 DEFUN (vtysh_start_zsh
,
4084 vtysh_start_zsh_cmd
,
4086 "Start UNIX shell\n"
4089 execute_command("zsh", 0, NULL
, NULL
);
4096 "list [permutations]",
4097 "Print command list\n"
4098 "Print all possible command permutations\n")
4100 return cmd_list_cmds(vty
, argc
== 2);
4103 DEFUN (vtysh_output_file
,
4104 vtysh_output_file_cmd
,
4106 "Direct vtysh output to file\n"
4107 "Direct vtysh output to file\n"
4108 "Path to dump output to\n")
4110 const char *path
= argv
[argc
- 1]->arg
;
4111 vty
->of
= fopen(path
, "a");
4113 vty_out(vty
, "Failed to open file '%s': %s\n", path
,
4114 safe_strerror(errno
));
4120 DEFUN (no_vtysh_output_file
,
4121 no_vtysh_output_file_cmd
,
4122 "no output file [FILE]",
4124 "Direct vtysh output to file\n"
4125 "Direct vtysh output to file\n"
4126 "Path to dump output to\n")
4128 if (vty
->of
!= stdout
) {
4138 "Find CLI command matching a regular expression\n"
4139 "Search pattern (POSIX regex)\n")
4141 return cmd_find_cmds(vty
, argv
, argc
);
4144 DEFUN_HIDDEN(show_cli_graph_vtysh
,
4145 show_cli_graph_vtysh_cmd
,
4149 "Dump current command space as DOT graph\n")
4151 struct cmd_node
*cn
= vector_slot(cmdvec
, vty
->node
);
4152 char *dot
= cmd_graph_dump_dot(cn
->cmdgraph
);
4154 vty_out(vty
, "%s\n", dot
);
4155 XFREE(MTYPE_TMP
, dot
);
4159 static void vtysh_install_default(enum node_type node
)
4161 _install_element(node
, &config_list_cmd
);
4162 _install_element(node
, &find_cmd
);
4163 _install_element(node
, &show_cli_graph_vtysh_cmd
);
4164 _install_element(node
, &vtysh_output_file_cmd
);
4165 _install_element(node
, &no_vtysh_output_file_cmd
);
4168 /* Making connection to protocol daemon. */
4169 static int vtysh_connect(struct vtysh_client
*vclient
)
4173 struct sockaddr_un addr
;
4177 if (!vclient
->path
[0])
4178 snprintf(vclient
->path
, sizeof(vclient
->path
), "%s/%s.vty",
4179 vtydir
, vclient
->name
);
4180 path
= vclient
->path
;
4182 /* Stat socket to see if we have permission to access it. */
4183 ret
= stat(path
, &s_stat
);
4184 if (ret
< 0 && errno
!= ENOENT
) {
4185 fprintf(stderr
, "vtysh_connect(%s): stat = %s\n", path
,
4186 safe_strerror(errno
));
4191 if (!S_ISSOCK(s_stat
.st_mode
)) {
4192 fprintf(stderr
, "vtysh_connect(%s): Not a socket\n",
4198 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
4201 fprintf(stderr
, "vtysh_connect(%s): socket = %s\n", path
,
4202 safe_strerror(errno
));
4207 memset(&addr
, 0, sizeof(addr
));
4208 addr
.sun_family
= AF_UNIX
;
4209 strlcpy(addr
.sun_path
, path
, sizeof(addr
.sun_path
));
4210 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
4211 len
= addr
.sun_len
= SUN_LEN(&addr
);
4213 len
= sizeof(addr
.sun_family
) + strlen(addr
.sun_path
);
4214 #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
4216 ret
= connect(sock
, (struct sockaddr
*)&addr
, len
);
4219 fprintf(stderr
, "vtysh_connect(%s): connect = %s\n", path
,
4220 safe_strerror(errno
));
4230 static int vtysh_reconnect(struct vtysh_client
*vclient
)
4234 fprintf(stderr
, "Warning: connecting to %s...", vclient
->name
);
4235 ret
= vtysh_connect(vclient
);
4237 fprintf(stderr
, "failed!\n");
4240 fprintf(stderr
, "success!\n");
4241 if (vtysh_client_execute(vclient
, "enable") < 0)
4243 return vtysh_execute_no_pager("end");
4246 /* Return true if str ends with suffix, else return false */
4247 static int ends_with(const char *str
, const char *suffix
)
4249 if (!str
|| !suffix
)
4251 size_t lenstr
= strlen(str
);
4252 size_t lensuffix
= strlen(suffix
);
4253 if (lensuffix
> lenstr
)
4255 return strncmp(str
+ lenstr
- lensuffix
, suffix
, lensuffix
) == 0;
4258 static void vtysh_client_sorted_insert(struct vtysh_client
*head_client
,
4259 struct vtysh_client
*client
)
4261 struct vtysh_client
*prev_node
, *current_node
;
4263 prev_node
= head_client
;
4264 current_node
= head_client
->next
;
4265 while (current_node
) {
4266 if (strcmp(current_node
->path
, client
->path
) > 0)
4269 prev_node
= current_node
;
4270 current_node
= current_node
->next
;
4272 client
->next
= current_node
;
4273 prev_node
->next
= client
;
4276 #define MAXIMUM_INSTANCES 10
4278 static void vtysh_update_all_instances(struct vtysh_client
*head_client
)
4280 struct vtysh_client
*client
;
4282 struct dirent
*file
;
4285 if (head_client
->flag
!= VTYSH_OSPFD
)
4288 /* ls vty_sock_dir and look for all files ending in .vty */
4289 dir
= opendir(vtydir
);
4291 while ((file
= readdir(dir
)) != NULL
) {
4292 if (frrstr_startswith(file
->d_name
, "ospfd-")
4293 && ends_with(file
->d_name
, ".vty")) {
4294 if (n
== MAXIMUM_INSTANCES
) {
4296 "Parsing %s, client limit(%d) reached!\n",
4300 client
= (struct vtysh_client
*)malloc(
4301 sizeof(struct vtysh_client
));
4303 client
->name
= "ospfd";
4304 client
->flag
= VTYSH_OSPFD
;
4305 snprintf(client
->path
, sizeof(client
->path
),
4306 "%s/%s", vtydir
, file
->d_name
);
4307 client
->next
= NULL
;
4308 vtysh_client_sorted_insert(head_client
, client
);
4316 static int vtysh_connect_all_instances(struct vtysh_client
*head_client
)
4318 struct vtysh_client
*client
;
4321 vtysh_update_all_instances(head_client
);
4323 client
= head_client
->next
;
4325 if (vtysh_connect(client
) == 0)
4327 client
= client
->next
;
4333 int vtysh_connect_all(const char *daemon_name
)
4339 for (i
= 0; i
< array_size(vtysh_client
); i
++) {
4341 || !strcmp(daemon_name
, vtysh_client
[i
].name
)) {
4343 if (vtysh_connect(&vtysh_client
[i
]) == 0)
4346 rc
+= vtysh_connect_all_instances(&vtysh_client
[i
]);
4350 fprintf(stderr
, "Error: no daemons match name %s!\n",
4355 /* To disable readline's filename completion. */
4356 static char *vtysh_completion_entry_function(const char *ignore
,
4362 void vtysh_readline_init(void)
4364 /* readline related settings. */
4365 char *disable_bracketed_paste
=
4366 XSTRDUP(MTYPE_TMP
, "set enable-bracketed-paste off");
4369 rl_parse_and_bind(disable_bracketed_paste
);
4370 rl_bind_key('?', (rl_command_func_t
*)vtysh_rl_describe
);
4371 rl_completion_entry_function
= vtysh_completion_entry_function
;
4372 rl_attempted_completion_function
= new_completion
;
4374 XFREE(MTYPE_TMP
, disable_bracketed_paste
);
4377 char *vtysh_prompt(void)
4379 static char buf
[512];
4381 #pragma GCC diagnostic push
4382 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
4383 /* prompt formatting has a %s in the cmd_node prompt string. */
4384 snprintf(buf
, sizeof(buf
), cmd_prompt(vty
->node
), cmd_hostname_get());
4385 #pragma GCC diagnostic pop
4389 static void vtysh_ac_line(void *arg
, const char *line
)
4393 for (i
= 0; i
< vector_active(comps
); i
++)
4394 if (!strcmp(line
, (char *)vector_slot(comps
, i
)))
4396 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, line
));
4399 static void vtysh_autocomplete(vector comps
, struct cmd_token
*token
)
4404 snprintf(accmd
, sizeof(accmd
), "autocomplete %d %s %s", token
->type
,
4405 token
->text
, token
->varname
? token
->varname
: "-");
4407 vty
->of_saved
= vty
->of
;
4409 for (i
= 0; i
< array_size(vtysh_client
); i
++)
4410 vtysh_client_run_all(&vtysh_client
[i
], accmd
, 1, vtysh_ac_line
,
4412 vty
->of
= vty
->of_saved
;
4415 static const struct cmd_variable_handler vtysh_var_handler
[] = {
4419 .completions
= vtysh_autocomplete
},
4420 {.completions
= NULL
}};
4422 void vtysh_uninit(void)
4424 if (vty
->of
!= stdout
)
4428 void vtysh_init_vty(void)
4430 struct stat st_out
, st_err
;
4432 cmd_defer_tree(true);
4434 for (size_t i
= 0; i
< array_size(vtysh_client
); i
++) {
4435 vtysh_client
[i
].fd
= -1;
4436 vtysh_client
[i
].log_fd
= -1;
4439 stderr_tty
= isatty(STDERR_FILENO
);
4441 if (fstat(STDOUT_FILENO
, &st_out
) || fstat(STDERR_FILENO
, &st_err
) ||
4442 (st_out
.st_dev
== st_err
.st_dev
&& st_out
.st_ino
== st_err
.st_ino
))
4443 stderr_stdout_same
= true;
4445 /* Make vty structure. */
4447 vty
->type
= VTY_SHELL
;
4448 vty
->node
= VIEW_NODE
;
4450 /* set default output */
4452 vtysh_pager_envdef(false);
4454 /* Initialize commands. */
4456 cmd_variable_handler_register(vtysh_var_handler
);
4460 install_node(&bgp_node
);
4461 install_element(CONFIG_NODE
, &router_bgp_cmd
);
4462 install_element(BGP_NODE
, &vtysh_exit_bgpd_cmd
);
4463 install_element(BGP_NODE
, &vtysh_quit_bgpd_cmd
);
4464 install_element(BGP_NODE
, &vtysh_end_all_cmd
);
4466 install_node(&bgp_vpnv4_node
);
4467 install_element(BGP_NODE
, &address_family_ipv4_vpn_cmd
);
4468 #ifdef KEEP_OLD_VPN_COMMANDS
4469 install_element(BGP_NODE
, &address_family_vpnv4_cmd
);
4470 #endif /* KEEP_OLD_VPN_COMMANDS */
4471 install_element(BGP_VPNV4_NODE
, &vtysh_exit_bgpd_cmd
);
4472 install_element(BGP_VPNV4_NODE
, &vtysh_quit_bgpd_cmd
);
4473 install_element(BGP_VPNV4_NODE
, &vtysh_end_all_cmd
);
4474 install_element(BGP_VPNV4_NODE
, &exit_address_family_cmd
);
4476 install_node(&bgp_vpnv6_node
);
4477 install_element(BGP_NODE
, &address_family_ipv6_vpn_cmd
);
4478 #ifdef KEEP_OLD_VPN_COMMANDS
4479 install_element(BGP_NODE
, &address_family_vpnv6_cmd
);
4480 #endif /* KEEP_OLD_VPN_COMMANDS */
4481 install_element(BGP_VPNV6_NODE
, &vtysh_exit_bgpd_cmd
);
4482 install_element(BGP_VPNV6_NODE
, &vtysh_quit_bgpd_cmd
);
4483 install_element(BGP_VPNV6_NODE
, &vtysh_end_all_cmd
);
4484 install_element(BGP_VPNV6_NODE
, &exit_address_family_cmd
);
4486 install_node(&bgp_flowspecv4_node
);
4487 install_element(BGP_NODE
, &address_family_flowspecv4_cmd
);
4488 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_exit_bgpd_cmd
);
4489 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_quit_bgpd_cmd
);
4490 install_element(BGP_FLOWSPECV4_NODE
, &vtysh_end_all_cmd
);
4491 install_element(BGP_FLOWSPECV4_NODE
, &exit_address_family_cmd
);
4493 install_node(&bgp_flowspecv6_node
);
4494 install_element(BGP_NODE
, &address_family_flowspecv6_cmd
);
4495 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_exit_bgpd_cmd
);
4496 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_quit_bgpd_cmd
);
4497 install_element(BGP_FLOWSPECV6_NODE
, &vtysh_end_all_cmd
);
4498 install_element(BGP_FLOWSPECV6_NODE
, &exit_address_family_cmd
);
4500 install_node(&bgp_ipv4_node
);
4501 install_element(BGP_NODE
, &address_family_ipv4_cmd
);
4502 install_element(BGP_IPV4_NODE
, &vtysh_exit_bgpd_cmd
);
4503 install_element(BGP_IPV4_NODE
, &vtysh_quit_bgpd_cmd
);
4504 install_element(BGP_IPV4_NODE
, &vtysh_end_all_cmd
);
4505 install_element(BGP_IPV4_NODE
, &exit_address_family_cmd
);
4507 install_node(&bgp_ipv4m_node
);
4508 install_element(BGP_NODE
, &address_family_ipv4_multicast_cmd
);
4509 install_element(BGP_IPV4M_NODE
, &vtysh_exit_bgpd_cmd
);
4510 install_element(BGP_IPV4M_NODE
, &vtysh_quit_bgpd_cmd
);
4511 install_element(BGP_IPV4M_NODE
, &vtysh_end_all_cmd
);
4512 install_element(BGP_IPV4M_NODE
, &exit_address_family_cmd
);
4514 install_node(&bgp_ipv4l_node
);
4515 install_element(BGP_NODE
, &address_family_ipv4_labeled_unicast_cmd
);
4516 install_element(BGP_IPV4L_NODE
, &vtysh_exit_bgpd_cmd
);
4517 install_element(BGP_IPV4L_NODE
, &vtysh_quit_bgpd_cmd
);
4518 install_element(BGP_IPV4L_NODE
, &vtysh_end_all_cmd
);
4519 install_element(BGP_IPV4L_NODE
, &exit_address_family_cmd
);
4521 install_node(&bgp_ipv6_node
);
4522 install_element(BGP_NODE
, &address_family_ipv6_cmd
);
4523 install_element(BGP_IPV6_NODE
, &vtysh_exit_bgpd_cmd
);
4524 install_element(BGP_IPV6_NODE
, &vtysh_quit_bgpd_cmd
);
4525 install_element(BGP_IPV6_NODE
, &vtysh_end_all_cmd
);
4526 install_element(BGP_IPV6_NODE
, &exit_address_family_cmd
);
4528 install_node(&bgp_ipv6m_node
);
4529 install_element(BGP_NODE
, &address_family_ipv6_multicast_cmd
);
4530 install_element(BGP_IPV6M_NODE
, &vtysh_exit_bgpd_cmd
);
4531 install_element(BGP_IPV6M_NODE
, &vtysh_quit_bgpd_cmd
);
4532 install_element(BGP_IPV6M_NODE
, &vtysh_end_all_cmd
);
4533 install_element(BGP_IPV6M_NODE
, &exit_address_family_cmd
);
4535 install_node(&bgp_ipv6l_node
);
4536 install_element(BGP_NODE
, &address_family_ipv6_labeled_unicast_cmd
);
4537 install_element(BGP_IPV6L_NODE
, &vtysh_exit_bgpd_cmd
);
4538 install_element(BGP_IPV6L_NODE
, &vtysh_quit_bgpd_cmd
);
4539 install_element(BGP_IPV6L_NODE
, &vtysh_end_all_cmd
);
4540 install_element(BGP_IPV6L_NODE
, &exit_address_family_cmd
);
4542 #if defined(ENABLE_BGP_VNC)
4543 install_node(&bgp_vrf_policy_node
);
4544 install_element(BGP_NODE
, &vnc_vrf_policy_cmd
);
4545 install_element(BGP_VRF_POLICY_NODE
, &vtysh_exit_bgpd_cmd
);
4546 install_element(BGP_VRF_POLICY_NODE
, &vtysh_quit_bgpd_cmd
);
4547 install_element(BGP_VRF_POLICY_NODE
, &vtysh_end_all_cmd
);
4548 install_element(BGP_VRF_POLICY_NODE
, &exit_vrf_policy_cmd
);
4550 install_node(&bgp_vnc_defaults_node
);
4551 install_element(BGP_NODE
, &vnc_defaults_cmd
);
4552 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_exit_bgpd_cmd
);
4553 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_quit_bgpd_cmd
);
4554 install_element(BGP_VNC_DEFAULTS_NODE
, &vtysh_end_all_cmd
);
4555 install_element(BGP_VNC_DEFAULTS_NODE
, &exit_vnc_config_cmd
);
4557 install_node(&bgp_vnc_nve_group_node
);
4558 install_element(BGP_NODE
, &vnc_nve_group_cmd
);
4559 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4560 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4561 install_element(BGP_VNC_NVE_GROUP_NODE
, &vtysh_end_all_cmd
);
4562 install_element(BGP_VNC_NVE_GROUP_NODE
, &exit_vnc_config_cmd
);
4564 install_node(&bgp_vnc_l2_group_node
);
4565 install_element(BGP_NODE
, &vnc_l2_group_cmd
);
4566 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_exit_bgpd_cmd
);
4567 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_quit_bgpd_cmd
);
4568 install_element(BGP_VNC_L2_GROUP_NODE
, &vtysh_end_all_cmd
);
4569 install_element(BGP_VNC_L2_GROUP_NODE
, &exit_vnc_config_cmd
);
4572 install_node(&bgp_evpn_node
);
4573 install_element(BGP_NODE
, &address_family_evpn_cmd
);
4574 install_element(BGP_EVPN_NODE
, &vtysh_quit_bgpd_cmd
);
4575 install_element(BGP_EVPN_NODE
, &vtysh_exit_bgpd_cmd
);
4576 install_element(BGP_EVPN_NODE
, &vtysh_end_all_cmd
);
4577 install_element(BGP_EVPN_NODE
, &exit_address_family_cmd
);
4579 install_node(&bgp_evpn_vni_node
);
4580 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
4581 install_element(BGP_EVPN_VNI_NODE
, &vtysh_exit_bgpd_cmd
);
4582 install_element(BGP_EVPN_VNI_NODE
, &vtysh_quit_bgpd_cmd
);
4583 install_element(BGP_EVPN_VNI_NODE
, &vtysh_end_all_cmd
);
4584 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
4586 install_node(&rpki_node
);
4587 install_element(CONFIG_NODE
, &rpki_cmd
);
4588 install_element(RPKI_NODE
, &rpki_exit_cmd
);
4589 install_element(RPKI_NODE
, &rpki_quit_cmd
);
4590 install_element(RPKI_NODE
, &vtysh_end_all_cmd
);
4592 install_node(&bmp_node
);
4593 install_element(BGP_NODE
, &bmp_targets_cmd
);
4594 install_element(BMP_NODE
, &bmp_exit_cmd
);
4595 install_element(BMP_NODE
, &bmp_quit_cmd
);
4596 install_element(BMP_NODE
, &vtysh_end_all_cmd
);
4598 install_node(&bgp_srv6_node
);
4599 install_element(BGP_NODE
, &bgp_srv6_cmd
);
4600 install_element(BGP_SRV6_NODE
, &exit_bgp_srv6_cmd
);
4601 install_element(BGP_SRV6_NODE
, &quit_bgp_srv6_cmd
);
4602 install_element(BGP_SRV6_NODE
, &vtysh_end_all_cmd
);
4603 #endif /* HAVE_BGPD */
4606 install_node(&rip_node
);
4608 install_element(CONFIG_NODE
, &router_rip_cmd
);
4609 install_element(RIP_NODE
, &vtysh_exit_ripd_cmd
);
4610 install_element(RIP_NODE
, &vtysh_quit_ripd_cmd
);
4611 install_element(RIP_NODE
, &vtysh_end_all_cmd
);
4612 #endif /* HAVE_RIPD */
4615 install_node(&ripng_node
);
4617 install_element(CONFIG_NODE
, &router_ripng_cmd
);
4618 install_element(RIPNG_NODE
, &vtysh_exit_ripngd_cmd
);
4619 install_element(RIPNG_NODE
, &vtysh_quit_ripngd_cmd
);
4620 install_element(RIPNG_NODE
, &vtysh_end_all_cmd
);
4621 #endif /* HAVE_RIPNGD */
4625 install_node(&ospf_node
);
4626 install_element(CONFIG_NODE
, &router_ospf_cmd
);
4627 install_element(OSPF_NODE
, &vtysh_exit_ospfd_cmd
);
4628 install_element(OSPF_NODE
, &vtysh_quit_ospfd_cmd
);
4629 install_element(OSPF_NODE
, &vtysh_end_all_cmd
);
4630 #endif /* HAVE_OSPFD */
4634 install_node(&ospf6_node
);
4635 install_element(CONFIG_NODE
, &router_ospf6_cmd
);
4636 install_element(OSPF6_NODE
, &vtysh_exit_ospf6d_cmd
);
4637 install_element(OSPF6_NODE
, &vtysh_quit_ospf6d_cmd
);
4638 install_element(OSPF6_NODE
, &vtysh_end_all_cmd
);
4639 #endif /* HAVE_OSPF6D */
4642 #if defined(HAVE_LDPD)
4643 install_node(&ldp_node
);
4644 install_element(CONFIG_NODE
, &ldp_mpls_ldp_cmd
);
4645 install_element(LDP_NODE
, &vtysh_exit_ldpd_cmd
);
4646 install_element(LDP_NODE
, &vtysh_quit_ldpd_cmd
);
4647 install_element(LDP_NODE
, &vtysh_end_all_cmd
);
4649 install_node(&ldp_ipv4_node
);
4650 install_element(LDP_NODE
, &ldp_address_family_ipv4_cmd
);
4651 install_element(LDP_IPV4_NODE
, &vtysh_exit_ldpd_cmd
);
4652 install_element(LDP_IPV4_NODE
, &vtysh_quit_ldpd_cmd
);
4653 install_element(LDP_IPV4_NODE
, &ldp_exit_address_family_cmd
);
4654 install_element(LDP_IPV4_NODE
, &vtysh_end_all_cmd
);
4656 install_node(&ldp_ipv6_node
);
4657 install_element(LDP_NODE
, &ldp_address_family_ipv6_cmd
);
4658 install_element(LDP_IPV6_NODE
, &vtysh_exit_ldpd_cmd
);
4659 install_element(LDP_IPV6_NODE
, &vtysh_quit_ldpd_cmd
);
4660 install_element(LDP_IPV6_NODE
, &ldp_exit_address_family_cmd
);
4661 install_element(LDP_IPV6_NODE
, &vtysh_end_all_cmd
);
4663 install_node(&ldp_ipv4_iface_node
);
4664 install_element(LDP_IPV4_NODE
, &ldp_interface_ifname_cmd
);
4665 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4666 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4667 install_element(LDP_IPV4_IFACE_NODE
, &vtysh_end_all_cmd
);
4669 install_node(&ldp_ipv6_iface_node
);
4670 install_element(LDP_IPV6_NODE
, &ldp_interface_ifname_cmd
);
4671 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_exit_ldpd_cmd
);
4672 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_quit_ldpd_cmd
);
4673 install_element(LDP_IPV6_IFACE_NODE
, &vtysh_end_all_cmd
);
4675 install_node(&ldp_l2vpn_node
);
4676 install_element(CONFIG_NODE
, &ldp_l2vpn_word_type_vpls_cmd
);
4677 install_element(LDP_L2VPN_NODE
, &vtysh_exit_ldpd_cmd
);
4678 install_element(LDP_L2VPN_NODE
, &vtysh_quit_ldpd_cmd
);
4679 install_element(LDP_L2VPN_NODE
, &vtysh_end_all_cmd
);
4681 install_node(&ldp_pseudowire_node
);
4682 install_element(LDP_L2VPN_NODE
, &ldp_member_pseudowire_ifname_cmd
);
4683 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_exit_ldpd_cmd
);
4684 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_quit_ldpd_cmd
);
4685 install_element(LDP_PSEUDOWIRE_NODE
, &vtysh_end_all_cmd
);
4690 install_node(&eigrp_node
);
4691 install_element(CONFIG_NODE
, &router_eigrp_cmd
);
4692 install_element(EIGRP_NODE
, &vtysh_exit_eigrpd_cmd
);
4693 install_element(EIGRP_NODE
, &vtysh_quit_eigrpd_cmd
);
4694 install_element(EIGRP_NODE
, &vtysh_end_all_cmd
);
4695 #endif /* HAVE_EIGRPD */
4699 install_node(&babel_node
);
4700 install_element(CONFIG_NODE
, &router_babel_cmd
);
4701 install_element(BABEL_NODE
, &vtysh_exit_babeld_cmd
);
4702 install_element(BABEL_NODE
, &vtysh_quit_babeld_cmd
);
4703 install_element(BABEL_NODE
, &vtysh_end_all_cmd
);
4704 #endif /* HAVE_BABELD */
4708 install_node(&isis_node
);
4709 install_element(CONFIG_NODE
, &router_isis_cmd
);
4710 install_element(ISIS_NODE
, &vtysh_exit_isisd_cmd
);
4711 install_element(ISIS_NODE
, &vtysh_quit_isisd_cmd
);
4712 install_element(ISIS_NODE
, &vtysh_end_all_cmd
);
4713 #endif /* HAVE_ISISD */
4717 install_node(&openfabric_node
);
4718 install_element(CONFIG_NODE
, &router_openfabric_cmd
);
4719 install_element(OPENFABRIC_NODE
, &vtysh_exit_fabricd_cmd
);
4720 install_element(OPENFABRIC_NODE
, &vtysh_quit_fabricd_cmd
);
4721 install_element(OPENFABRIC_NODE
, &vtysh_end_all_cmd
);
4722 #endif /* HAVE_FABRICD */
4726 install_node(&pbr_map_node
);
4727 install_element(CONFIG_NODE
, &vtysh_pbr_map_cmd
);
4728 install_element(CONFIG_NODE
, &vtysh_no_pbr_map_cmd
);
4729 install_element(PBRMAP_NODE
, &vtysh_exit_pbr_map_cmd
);
4730 install_element(PBRMAP_NODE
, &vtysh_quit_pbr_map_cmd
);
4731 install_element(PBRMAP_NODE
, &vtysh_end_all_cmd
);
4732 #endif /* HAVE_PBRD */
4736 install_node(&bfd_node
);
4737 install_element(CONFIG_NODE
, &bfd_enter_cmd
);
4738 install_element(BFD_NODE
, &vtysh_exit_bfdd_cmd
);
4739 install_element(BFD_NODE
, &vtysh_quit_bfdd_cmd
);
4740 install_element(BFD_NODE
, &vtysh_end_all_cmd
);
4742 install_node(&bfd_peer_node
);
4743 install_element(BFD_NODE
, &bfd_peer_enter_cmd
);
4744 install_element(BFD_PEER_NODE
, &vtysh_exit_bfdd_cmd
);
4745 install_element(BFD_PEER_NODE
, &vtysh_quit_bfdd_cmd
);
4746 install_element(BFD_PEER_NODE
, &vtysh_end_all_cmd
);
4748 install_node(&bfd_profile_node
);
4749 install_element(BFD_NODE
, &bfd_profile_enter_cmd
);
4750 install_element(BFD_PROFILE_NODE
, &vtysh_exit_bfdd_cmd
);
4751 install_element(BFD_PROFILE_NODE
, &vtysh_quit_bfdd_cmd
);
4752 install_element(BFD_PROFILE_NODE
, &vtysh_end_all_cmd
);
4753 #endif /* HAVE_BFDD */
4755 install_node(&segment_routing_node
);
4756 install_element(CONFIG_NODE
, &segment_routing_cmd
);
4757 install_element(SEGMENT_ROUTING_NODE
, &vtysh_exit_sr_cmd
);
4758 install_element(SEGMENT_ROUTING_NODE
, &vtysh_quit_sr_cmd
);
4759 install_element(SEGMENT_ROUTING_NODE
, &vtysh_end_all_cmd
);
4761 #if defined(HAVE_PATHD)
4762 install_node(&sr_traffic_eng_node
);
4763 install_node(&srte_segment_list_node
);
4764 install_node(&srte_policy_node
);
4765 install_node(&srte_candidate_dyn_node
);
4767 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_exit_pathd_cmd
);
4768 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_quit_pathd_cmd
);
4769 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_exit_pathd_cmd
);
4770 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_quit_pathd_cmd
);
4771 install_element(SR_POLICY_NODE
, &vtysh_exit_pathd_cmd
);
4772 install_element(SR_POLICY_NODE
, &vtysh_quit_pathd_cmd
);
4773 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_exit_pathd_cmd
);
4774 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_quit_pathd_cmd
);
4777 install_element(SR_TRAFFIC_ENG_NODE
, &vtysh_end_all_cmd
);
4778 install_element(SR_SEGMENT_LIST_NODE
, &vtysh_end_all_cmd
);
4779 install_element(SR_POLICY_NODE
, &vtysh_end_all_cmd
);
4780 install_element(SR_CANDIDATE_DYN_NODE
, &vtysh_end_all_cmd
);
4782 install_element(SEGMENT_ROUTING_NODE
, &sr_traffic_eng_cmd
);
4783 install_element(SR_TRAFFIC_ENG_NODE
, &srte_segment_list_cmd
);
4784 install_element(SR_TRAFFIC_ENG_NODE
, &srte_policy_cmd
);
4785 install_element(SR_POLICY_NODE
, &srte_policy_candidate_dyn_path_cmd
);
4787 install_node(&pcep_node
);
4788 install_node(&pcep_pcc_node
);
4789 install_node(&pcep_pce_node
);
4790 install_node(&pcep_pce_config_node
);
4792 install_element(PCEP_NODE
, &vtysh_exit_pathd_cmd
);
4793 install_element(PCEP_NODE
, &vtysh_quit_pathd_cmd
);
4794 install_element(PCEP_PCC_NODE
, &vtysh_exit_pathd_cmd
);
4795 install_element(PCEP_PCC_NODE
, &vtysh_quit_pathd_cmd
);
4796 install_element(PCEP_PCE_NODE
, &vtysh_exit_pathd_cmd
);
4797 install_element(PCEP_PCE_NODE
, &vtysh_quit_pathd_cmd
);
4798 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_exit_pathd_cmd
);
4799 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_quit_pathd_cmd
);
4801 install_element(PCEP_NODE
, &vtysh_end_all_cmd
);
4802 install_element(PCEP_PCC_NODE
, &vtysh_end_all_cmd
);
4803 install_element(PCEP_PCE_NODE
, &vtysh_end_all_cmd
);
4804 install_element(PCEP_PCE_CONFIG_NODE
, &vtysh_end_all_cmd
);
4806 install_element(SR_TRAFFIC_ENG_NODE
, &pcep_cmd
);
4807 install_element(PCEP_NODE
, &pcep_cli_pcc_cmd
);
4808 install_element(PCEP_NODE
, &pcep_cli_pcep_pce_config_cmd
);
4809 install_element(PCEP_NODE
, &pcep_cli_pce_cmd
);
4811 #endif /* HAVE_PATHD */
4814 install_node(&keychain_node
);
4815 install_element(CONFIG_NODE
, &key_chain_cmd
);
4816 install_element(KEYCHAIN_NODE
, &key_chain_cmd
);
4817 install_element(KEYCHAIN_NODE
, &vtysh_exit_keys_cmd
);
4818 install_element(KEYCHAIN_NODE
, &vtysh_quit_keys_cmd
);
4819 install_element(KEYCHAIN_NODE
, &vtysh_end_all_cmd
);
4821 install_node(&keychain_key_node
);
4822 install_element(KEYCHAIN_NODE
, &key_cmd
);
4823 install_element(KEYCHAIN_KEY_NODE
, &key_chain_cmd
);
4824 install_element(KEYCHAIN_KEY_NODE
, &vtysh_exit_keys_cmd
);
4825 install_element(KEYCHAIN_KEY_NODE
, &vtysh_quit_keys_cmd
);
4826 install_element(KEYCHAIN_KEY_NODE
, &vtysh_end_all_cmd
);
4829 install_node(&nh_group_node
);
4830 install_element(CONFIG_NODE
, &vtysh_nexthop_group_cmd
);
4831 install_element(CONFIG_NODE
, &vtysh_no_nexthop_group_cmd
);
4832 install_element(NH_GROUP_NODE
, &vtysh_end_all_cmd
);
4833 install_element(NH_GROUP_NODE
, &vtysh_exit_nexthop_group_cmd
);
4834 install_element(NH_GROUP_NODE
, &vtysh_quit_nexthop_group_cmd
);
4837 install_node(&zebra_node
);
4839 install_node(&interface_node
);
4840 install_element(CONFIG_NODE
, &vtysh_interface_cmd
);
4841 install_element(INTERFACE_NODE
, &vtysh_end_all_cmd
);
4842 install_element(INTERFACE_NODE
, &vtysh_exit_interface_cmd
);
4843 install_element(INTERFACE_NODE
, &vtysh_quit_interface_cmd
);
4845 install_node(&link_params_node
);
4846 install_element(INTERFACE_NODE
, &vtysh_link_params_cmd
);
4847 install_element(LINK_PARAMS_NODE
, &exit_link_params_cmd
);
4848 install_element(LINK_PARAMS_NODE
, &vtysh_end_all_cmd
);
4849 install_element(LINK_PARAMS_NODE
, &vtysh_exit_link_params_cmd
);
4850 install_element(LINK_PARAMS_NODE
, &vtysh_quit_link_params_cmd
);
4852 install_node(&pw_node
);
4853 install_element(CONFIG_NODE
, &vtysh_pseudowire_cmd
);
4854 install_element(PW_NODE
, &vtysh_end_all_cmd
);
4855 install_element(PW_NODE
, &vtysh_exit_pseudowire_cmd
);
4856 install_element(PW_NODE
, &vtysh_quit_pseudowire_cmd
);
4858 install_node(&vrf_node
);
4859 install_element(CONFIG_NODE
, &vtysh_vrf_cmd
);
4860 install_element(VRF_NODE
, &exit_vrf_config_cmd
);
4861 install_element(VRF_NODE
, &vtysh_end_all_cmd
);
4862 install_element(VRF_NODE
, &vtysh_exit_vrf_cmd
);
4863 install_element(VRF_NODE
, &vtysh_quit_vrf_cmd
);
4865 install_element(CONFIG_NODE
, &vtysh_affinity_map_cmd
);
4866 install_element(CONFIG_NODE
, &vtysh_no_affinity_map_cmd
);
4868 install_node(&rmap_node
);
4869 install_element(CONFIG_NODE
, &vtysh_route_map_cmd
);
4870 install_element(RMAP_NODE
, &vtysh_exit_rmap_cmd
);
4871 install_element(RMAP_NODE
, &vtysh_quit_rmap_cmd
);
4872 install_element(RMAP_NODE
, &vtysh_end_all_cmd
);
4874 install_node(&vty_node
);
4875 install_element(CONFIG_NODE
, &vtysh_line_vty_cmd
);
4876 install_element(VTY_NODE
, &vtysh_exit_line_vty_cmd
);
4877 install_element(VTY_NODE
, &vtysh_quit_line_vty_cmd
);
4878 install_element(VTY_NODE
, &vtysh_end_all_cmd
);
4881 struct cmd_node
*node
;
4882 for (unsigned int i
= 0; i
< vector_active(cmdvec
); i
++) {
4883 node
= vector_slot(cmdvec
, i
);
4884 if (!node
|| node
->node
== VIEW_NODE
)
4886 vtysh_install_default(node
->node
);
4892 install_element(VIEW_NODE
, &vtysh_enable_cmd
);
4893 install_element(ENABLE_NODE
, &vtysh_config_terminal_cmd
);
4894 install_element(ENABLE_NODE
, &vtysh_disable_cmd
);
4896 /* "exit" command. */
4897 install_element(VIEW_NODE
, &vtysh_exit_all_cmd
);
4898 install_element(CONFIG_NODE
, &vtysh_exit_all_cmd
);
4899 install_element(VIEW_NODE
, &vtysh_quit_all_cmd
);
4900 install_element(CONFIG_NODE
, &vtysh_quit_all_cmd
);
4902 /* "end" command. */
4903 install_element(CONFIG_NODE
, &vtysh_end_all_cmd
);
4904 install_element(ENABLE_NODE
, &vtysh_end_all_cmd
);
4906 /* SRv6 Data-plane */
4907 install_node(&srv6_node
);
4908 install_element(SEGMENT_ROUTING_NODE
, &srv6_cmd
);
4909 install_element(SRV6_NODE
, &srv6_locators_cmd
);
4910 install_element(SRV6_NODE
, &exit_srv6_config_cmd
);
4911 install_element(SRV6_NODE
, &vtysh_end_all_cmd
);
4913 install_node(&srv6_locs_node
);
4914 install_element(SRV6_LOCS_NODE
, &srv6_locator_cmd
);
4915 install_element(SRV6_LOCS_NODE
, &exit_srv6_locs_config_cmd
);
4916 install_element(SRV6_LOCS_NODE
, &vtysh_end_all_cmd
);
4918 install_node(&srv6_loc_node
);
4919 install_element(SRV6_LOC_NODE
, &exit_srv6_loc_config_cmd
);
4920 install_element(SRV6_LOC_NODE
, &vtysh_end_all_cmd
);
4922 install_element(ENABLE_NODE
, &vtysh_show_running_config_cmd
);
4923 install_element(ENABLE_NODE
, &vtysh_copy_running_config_cmd
);
4924 install_element(ENABLE_NODE
, &vtysh_copy_to_running_cmd
);
4926 /* "write terminal" command. */
4927 install_element(ENABLE_NODE
, &vtysh_write_terminal_cmd
);
4929 install_element(CONFIG_NODE
, &vtysh_integrated_config_cmd
);
4930 install_element(CONFIG_NODE
, &no_vtysh_integrated_config_cmd
);
4932 /* "write memory" command. */
4933 install_element(ENABLE_NODE
, &vtysh_write_memory_cmd
);
4935 install_element(CONFIG_NODE
, &start_config_cmd
);
4936 install_element(CONFIG_NODE
, &end_config_cmd
);
4938 install_element(CONFIG_NODE
, &vtysh_terminal_paginate_cmd
);
4939 install_element(VIEW_NODE
, &vtysh_terminal_paginate_cmd
);
4940 install_element(VIEW_NODE
, &vtysh_terminal_length_cmd
);
4941 install_element(VIEW_NODE
, &vtysh_terminal_no_length_cmd
);
4942 install_element(VIEW_NODE
, &vtysh_show_daemons_cmd
);
4944 install_element(VIEW_NODE
, &vtysh_terminal_monitor_cmd
);
4945 install_element(VIEW_NODE
, &no_vtysh_terminal_monitor_cmd
);
4947 install_element(VIEW_NODE
, &vtysh_ping_cmd
);
4948 install_element(VIEW_NODE
, &vtysh_motd_cmd
);
4949 install_element(VIEW_NODE
, &vtysh_ping_ip_cmd
);
4950 install_element(VIEW_NODE
, &vtysh_traceroute_cmd
);
4951 install_element(VIEW_NODE
, &vtysh_traceroute_ip_cmd
);
4952 install_element(VIEW_NODE
, &vtysh_mtrace_cmd
);
4953 install_element(VIEW_NODE
, &vtysh_ping6_cmd
);
4954 install_element(VIEW_NODE
, &vtysh_traceroute6_cmd
);
4955 #if defined(HAVE_SHELL_ACCESS)
4956 install_element(VIEW_NODE
, &vtysh_telnet_cmd
);
4957 install_element(VIEW_NODE
, &vtysh_telnet_port_cmd
);
4958 install_element(VIEW_NODE
, &vtysh_ssh_cmd
);
4960 #if defined(HAVE_SHELL_ACCESS)
4961 install_element(ENABLE_NODE
, &vtysh_start_shell_cmd
);
4962 install_element(ENABLE_NODE
, &vtysh_start_bash_cmd
);
4963 install_element(ENABLE_NODE
, &vtysh_start_zsh_cmd
);
4967 install_element(VIEW_NODE
, &vtysh_show_error_code_cmd
);
4968 install_element(ENABLE_NODE
, &vtysh_show_debugging_cmd
);
4969 install_element(ENABLE_NODE
, &vtysh_show_debugging_hashtable_cmd
);
4970 install_element(ENABLE_NODE
, &vtysh_debug_all_cmd
);
4971 install_element(CONFIG_NODE
, &vtysh_debug_all_cmd
);
4972 install_element(ENABLE_NODE
, &vtysh_debug_memstats_cmd
);
4973 install_element(CONFIG_NODE
, &vtysh_debug_memstats_cmd
);
4974 install_element(ENABLE_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4975 install_element(CONFIG_NODE
, &vtysh_debug_uid_backtrace_cmd
);
4978 install_element(ENABLE_NODE
, &show_config_running_cmd
);
4979 install_element(ENABLE_NODE
, &show_yang_operational_data_cmd
);
4980 install_element(ENABLE_NODE
, &show_yang_module_cmd
);
4981 install_element(ENABLE_NODE
, &show_yang_module_detail_cmd
);
4982 install_element(ENABLE_NODE
, &debug_nb_cmd
);
4983 install_element(CONFIG_NODE
, &debug_nb_cmd
);
4985 /* misc lib show commands */
4986 install_element(VIEW_NODE
, &vtysh_show_history_cmd
);
4987 install_element(VIEW_NODE
, &vtysh_show_memory_cmd
);
4988 install_element(VIEW_NODE
, &vtysh_show_modules_cmd
);
4989 install_element(VIEW_NODE
, &vtysh_show_work_queues_cmd
);
4990 install_element(VIEW_NODE
, &vtysh_show_work_queues_daemon_cmd
);
4991 install_element(VIEW_NODE
, &vtysh_show_thread_cmd
);
4992 install_element(VIEW_NODE
, &vtysh_show_poll_cmd
);
4993 install_element(VIEW_NODE
, &vtysh_show_thread_timer_cmd
);
4996 install_element(VIEW_NODE
, &vtysh_show_logging_cmd
);
4998 install_element(CONFIG_NODE
, &vtysh_service_password_encrypt_cmd
);
4999 install_element(CONFIG_NODE
, &no_vtysh_service_password_encrypt_cmd
);
5001 install_element(CONFIG_NODE
, &vtysh_allow_reserved_ranges_cmd
);
5002 install_element(CONFIG_NODE
, &no_vtysh_allow_reserved_ranges_cmd
);
5004 install_element(CONFIG_NODE
, &vtysh_password_cmd
);
5005 install_element(CONFIG_NODE
, &no_vtysh_password_cmd
);
5006 install_element(CONFIG_NODE
, &vtysh_enable_password_cmd
);
5007 install_element(CONFIG_NODE
, &no_vtysh_enable_password_cmd
);