]> git.proxmox.com Git - mirror_frr.git/blob - vtysh/vtysh.c
Merge pull request #8920 from mjstapp/fix_bgp_adv_sa
[mirror_frr.git] / vtysh / vtysh.c
1 /* Virtual terminal interface shell.
2 * Copyright (C) 2000 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include <sys/un.h>
24 #include <setjmp.h>
25 #include <sys/wait.h>
26 #include <sys/resource.h>
27 #include <sys/stat.h>
28
29 #include <readline/readline.h>
30 #include <readline/history.h>
31
32 #include <dirent.h>
33 #include <stdio.h>
34 #include <string.h>
35
36 #include "linklist.h"
37 #include "command.h"
38 #include "memory.h"
39 #include "filter.h"
40 #include "vtysh/vtysh.h"
41 #include "vtysh/vtysh_daemons.h"
42 #include "log.h"
43 #include "ns.h"
44 #include "vrf.h"
45 #include "libfrr.h"
46 #include "command_graph.h"
47 #include "frrstr.h"
48 #include "json.h"
49 #include "ferr.h"
50
51 DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy");
52
53 /* Struct VTY. */
54 struct vty *vty;
55
56 /* VTY shell pager name. */
57 char *vtysh_pager_name = NULL;
58
59 /* VTY shell client structure */
60 struct vtysh_client {
61 int fd;
62 const char *name;
63 int flag;
64 char path[MAXPATHLEN];
65 struct vtysh_client *next;
66 };
67
68 /* Some utility functions for working on vtysh-specific vty tasks */
69
70 static FILE *vty_open_pager(struct vty *vty)
71 {
72 if (vty->is_paged)
73 return vty->of;
74
75 if (!vtysh_pager_name)
76 return NULL;
77
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;
82 perror("popen");
83 exit(1);
84 }
85
86 vty->is_paged = true;
87
88 return vty->of;
89 }
90
91 static int vty_close_pager(struct vty *vty)
92 {
93 if (!vty->is_paged)
94 return 0;
95
96 fflush(vty->of);
97 if (pclose(vty->of) == -1) {
98 perror("pclose");
99 exit(1);
100 }
101
102 vty->of = vty->of_saved;
103 vty->is_paged = false;
104
105 return 0;
106 }
107
108 static void vtysh_pager_envdef(bool fallback)
109 {
110 char *pager_defined;
111
112 pager_defined = getenv("VTYSH_PAGER");
113
114 if (pager_defined)
115 vtysh_pager_name = strdup(pager_defined);
116 else if (fallback)
117 vtysh_pager_name = strdup(VTYSH_PAGER);
118 }
119
120 /* --- */
121
122 struct vtysh_client vtysh_client[] = {
123 {.fd = -1, .name = "zebra", .flag = VTYSH_ZEBRA, .next = NULL},
124 {.fd = -1, .name = "ripd", .flag = VTYSH_RIPD, .next = NULL},
125 {.fd = -1, .name = "ripngd", .flag = VTYSH_RIPNGD, .next = NULL},
126 {.fd = -1, .name = "ospfd", .flag = VTYSH_OSPFD, .next = NULL},
127 {.fd = -1, .name = "ospf6d", .flag = VTYSH_OSPF6D, .next = NULL},
128 {.fd = -1, .name = "ldpd", .flag = VTYSH_LDPD, .next = NULL},
129 {.fd = -1, .name = "bgpd", .flag = VTYSH_BGPD, .next = NULL},
130 {.fd = -1, .name = "isisd", .flag = VTYSH_ISISD, .next = NULL},
131 {.fd = -1, .name = "pimd", .flag = VTYSH_PIMD, .next = NULL},
132 {.fd = -1, .name = "nhrpd", .flag = VTYSH_NHRPD, .next = NULL},
133 {.fd = -1, .name = "eigrpd", .flag = VTYSH_EIGRPD, .next = NULL},
134 {.fd = -1, .name = "babeld", .flag = VTYSH_BABELD, .next = NULL},
135 {.fd = -1, .name = "sharpd", .flag = VTYSH_SHARPD, .next = NULL},
136 {.fd = -1, .name = "fabricd", .flag = VTYSH_FABRICD, .next = NULL},
137 {.fd = -1, .name = "watchfrr", .flag = VTYSH_WATCHFRR, .next = NULL},
138 {.fd = -1, .name = "pbrd", .flag = VTYSH_PBRD, .next = NULL},
139 {.fd = -1, .name = "staticd", .flag = VTYSH_STATICD, .next = NULL},
140 {.fd = -1, .name = "bfdd", .flag = VTYSH_BFDD, .next = NULL},
141 {.fd = -1, .name = "vrrpd", .flag = VTYSH_VRRPD, .next = NULL},
142 {.fd = -1, .name = "pathd", .flag = VTYSH_PATHD, .next = NULL},
143 };
144
145 /* Searches for client by name, returns index */
146 static int vtysh_client_lookup(const char *name)
147 {
148 int idx = -1;
149
150 for (unsigned int i = 0; i < array_size(vtysh_client); i++) {
151 if (strmatch(vtysh_client[i].name, name)) {
152 idx = i;
153 break;
154 }
155 }
156
157 return idx;
158 }
159
160 enum vtysh_write_integrated vtysh_write_integrated =
161 WRITE_INTEGRATED_UNSPECIFIED;
162
163 static int vtysh_reconnect(struct vtysh_client *vclient);
164
165 static void vclient_close(struct vtysh_client *vclient)
166 {
167 if (vclient->fd >= 0) {
168 if (vty->of)
169 vty_out(vty,
170 "Warning: closing connection to %s because of an I/O error!\n",
171 vclient->name);
172 close(vclient->fd);
173 /* indicate as candidate for reconnect */
174 vclient->fd = VTYSH_WAS_ACTIVE;
175 }
176 }
177
178 /*
179 * Send a CLI command to a client and read the response.
180 *
181 * Output will be printed to vty->of. If you want to suppress output, set that
182 * to NULL.
183 *
184 * vclient
185 * the client to send the command to
186 *
187 * line
188 * the command to send
189 *
190 * callback
191 * if non-null, this will be called with each line of output received from
192 * the client passed in the second parameter
193 *
194 * cbarg
195 * optional first argument to pass to callback
196 *
197 * Returns:
198 * a status code
199 */
200 static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
201 void (*callback)(void *, const char *), void *cbarg)
202 {
203 int ret;
204 char stackbuf[4096];
205 char *buf = stackbuf;
206 size_t bufsz = sizeof(stackbuf);
207 char *bufvalid, *end = NULL;
208 char terminator[3] = {0, 0, 0};
209
210 /* vclinet was previously active, try to reconnect */
211 if (vclient->fd == VTYSH_WAS_ACTIVE) {
212 ret = vtysh_reconnect(vclient);
213 if (ret < 0)
214 goto out_err;
215 }
216
217 if (vclient->fd < 0)
218 return CMD_SUCCESS;
219
220 ret = write(vclient->fd, line, strlen(line) + 1);
221 if (ret <= 0) {
222 /* close connection and try to reconnect */
223 vclient_close(vclient);
224 ret = vtysh_reconnect(vclient);
225 if (ret < 0)
226 goto out_err;
227 /* retry line */
228 ret = write(vclient->fd, line, strlen(line) + 1);
229 if (ret <= 0)
230 goto out_err;
231 }
232
233 bufvalid = buf;
234 do {
235 ssize_t nread =
236 read(vclient->fd, bufvalid, buf + bufsz - bufvalid - 1);
237
238 if (nread < 0 && (errno == EINTR || errno == EAGAIN))
239 continue;
240
241 if (nread <= 0) {
242 if (vty->of)
243 vty_out(vty,
244 "vtysh: error reading from %s: %s (%d)",
245 vclient->name, safe_strerror(errno),
246 errno);
247 goto out_err;
248 }
249
250 bufvalid += nread;
251
252 /* Null terminate so we may pass this to *printf later. */
253 bufvalid[0] = '\0';
254
255 /*
256 * We expect string output from daemons, so instead of looking
257 * for the full 3 null bytes of the terminator, we check for
258 * just one instead and assume it is the first byte of the
259 * terminator. The presence of the full terminator is checked
260 * later.
261 */
262 if (bufvalid - buf >= 4)
263 end = memmem(bufvalid - 4, 4, "\0", 1);
264
265 /*
266 * calculate # bytes we have, up to & not including the
267 * terminator if present
268 */
269 size_t textlen = (end ? end : bufvalid) - buf;
270 bool b = false;
271
272 /* feed line processing callback if present */
273 while (callback && bufvalid > buf && (end > buf || !end)) {
274 textlen = (end ? end : bufvalid) - buf;
275 char *eol = memchr(buf, '\n', textlen);
276 if (eol)
277 /* line break */
278 *eol++ = '\0';
279 else if (end == buf)
280 /*
281 * no line break, end of input, no text left
282 * before end; nothing to write
283 */
284 b = true;
285 else if (end)
286 /* no nl, end of input, but some text left */
287 eol = end;
288 else if (bufvalid == buf + bufsz - 1) {
289 /*
290 * no nl, no end of input, no buffer space;
291 * realloc
292 */
293 char *new;
294
295 bufsz *= 2;
296 if (buf == stackbuf) {
297 new = XMALLOC(MTYPE_TMP, bufsz);
298 memcpy(new, stackbuf, sizeof(stackbuf));
299 } else
300 new = XREALLOC(MTYPE_TMP, buf, bufsz);
301
302 bufvalid = bufvalid - buf + new;
303 buf = new;
304 /* if end != NULL, we won't be reading more
305 * data... */
306 assert(end == NULL);
307 b = true;
308 } else
309 b = true;
310
311 if (b)
312 break;
313
314 /* eol is at line end now, either \n => \0 or \0\0\0 */
315 assert(eol && eol <= bufvalid);
316
317 if (vty->of)
318 vty_out(vty, "%s\n", buf);
319
320 callback(cbarg, buf);
321
322 /* shift back data and adjust bufvalid */
323 memmove(buf, eol, bufvalid - eol);
324 bufvalid -= eol - buf;
325 if (end)
326 end -= eol - buf;
327 }
328
329 /* else if no callback, dump raw */
330 if (!callback) {
331 if (vty->of)
332 vty_out(vty, "%s", buf);
333 memmove(buf, buf + textlen, bufvalid - buf - textlen);
334 bufvalid -= textlen;
335 if (end)
336 end -= textlen;
337
338 /*
339 * ----------------------------------------------------
340 * At this point `buf` should be in one of two states:
341 * - Empty (i.e. buf == bufvalid)
342 * - Contains up to 4 bytes of the terminator
343 * ----------------------------------------------------
344 */
345 assert(((buf == bufvalid)
346 || (bufvalid - buf <= 4 && buf[0] == 0x00)));
347 }
348
349 /* if we have the terminator, break */
350 if (end && bufvalid - buf == 4) {
351 assert(!memcmp(buf, terminator, 3));
352 ret = buf[3];
353 break;
354 }
355
356 } while (true);
357 goto out;
358
359 out_err:
360 vclient_close(vclient);
361 ret = CMD_SUCCESS;
362 out:
363 if (buf != stackbuf)
364 XFREE(MTYPE_TMP, buf);
365 return ret;
366 }
367
368 static int vtysh_client_run_all(struct vtysh_client *head_client,
369 const char *line, int continue_on_err,
370 void (*callback)(void *, const char *),
371 void *cbarg)
372 {
373 struct vtysh_client *client;
374 int rc, rc_all = CMD_SUCCESS;
375 int correct_instance = 0, wrong_instance = 0;
376
377 for (client = head_client; client; client = client->next) {
378 rc = vtysh_client_run(client, line, callback, cbarg);
379 if (rc == CMD_NOT_MY_INSTANCE) {
380 wrong_instance++;
381 continue;
382 }
383 if (client->fd > 0)
384 correct_instance++;
385 if (rc != CMD_SUCCESS) {
386 if (!continue_on_err)
387 return rc;
388 rc_all = rc;
389 }
390 }
391 if (wrong_instance && !correct_instance && vty->of) {
392 vty_out(vty,
393 "%% [%s]: command ignored as it targets an instance that is not running\n",
394 head_client->name);
395 rc_all = CMD_WARNING_CONFIG_FAILED;
396 }
397 return rc_all;
398 }
399
400 /*
401 * Execute command against all daemons.
402 *
403 * head_client
404 * where to start walking in the daemon list
405 *
406 * line
407 * the specific command to execute
408 *
409 * Returns:
410 * a status code
411 */
412 static int vtysh_client_execute(struct vtysh_client *head_client,
413 const char *line)
414 {
415 return vtysh_client_run_all(head_client, line, 0, NULL, NULL);
416 }
417
418 /* Execute by name */
419 static int vtysh_client_execute_name(const char *name, const char *line)
420 {
421 int ret = CMD_SUCCESS;
422 int idx_client = -1;
423
424 idx_client = vtysh_client_lookup(name);
425 if (idx_client != -1)
426 ret = vtysh_client_execute(&vtysh_client[idx_client], line);
427 else {
428 vty_out(vty, "Client not found\n");
429 ret = CMD_WARNING;
430 }
431
432 return ret;
433 }
434
435 /*
436 * Retrieve all running config from daemons and parse it with the vtysh config
437 * parser. Returned output is not displayed to the user.
438 *
439 * head_client
440 * where to start walking in the daemon list
441 *
442 * line
443 * the specific command to execute
444 */
445 static void vtysh_client_config(struct vtysh_client *head_client, char *line)
446 {
447 /* watchfrr currently doesn't load any config, and has some hardcoded
448 * settings that show up in "show run". skip it here (for now at
449 * least) so we don't get that mangled up in config-write.
450 */
451 if (head_client->flag == VTYSH_WATCHFRR)
452 return;
453
454 /* suppress output to user */
455 vty->of_saved = vty->of;
456 vty->of = NULL;
457 vtysh_client_run_all(head_client, line, 1, vtysh_config_parse_line,
458 NULL);
459 vty->of = vty->of_saved;
460 }
461
462 /* Command execution over the vty interface. */
463 static int vtysh_execute_func(const char *line, int pager)
464 {
465 int ret, cmd_stat;
466 unsigned int i;
467 vector vline;
468 const struct cmd_element *cmd;
469 int tried = 0;
470 int saved_ret, saved_node;
471
472 /* Split readline string up into the vector. */
473 vline = cmd_make_strvec(line);
474
475 if (vline == NULL)
476 return CMD_SUCCESS;
477
478 if (user_mode) {
479 if (strncmp("en", vector_slot(vline, 0), 2) == 0) {
480 cmd_free_strvec(vline);
481 vty_out(vty, "%% Command not allowed: enable\n");
482 return CMD_WARNING;
483 }
484 }
485
486 saved_ret = ret = cmd_execute(vty, line, &cmd, 1);
487 saved_node = vty->node;
488
489 /*
490 * If command doesn't succeeded in current node, try to walk up in node
491 * tree. Changing vty->node is enough to try it just out without actual
492 * walkup in the vtysh.
493 */
494 while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON
495 && ret != CMD_WARNING && ret != CMD_WARNING_CONFIG_FAILED
496 && ret != CMD_ERR_AMBIGUOUS && ret != CMD_ERR_INCOMPLETE
497 && vty->node > CONFIG_NODE) {
498 vty->node = node_parent(vty->node);
499 ret = cmd_execute(vty, line, &cmd, 1);
500 tried++;
501 }
502
503 vty->node = saved_node;
504
505 /*
506 * If command succeeded in any other node than current (tried > 0) we
507 * have to move into node in the vtysh where it succeeded.
508 */
509 if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON
510 || ret == CMD_WARNING) {
511 if ((saved_node == BGP_VPNV4_NODE
512 || saved_node == BGP_VPNV6_NODE
513 || saved_node == BGP_IPV4_NODE
514 || saved_node == BGP_IPV6_NODE
515 || saved_node == BGP_FLOWSPECV4_NODE
516 || saved_node == BGP_FLOWSPECV6_NODE
517 || saved_node == BGP_IPV4M_NODE
518 || saved_node == BGP_IPV4L_NODE
519 || saved_node == BGP_IPV6L_NODE
520 || saved_node == BGP_IPV6M_NODE
521 || saved_node == BGP_EVPN_NODE
522 || saved_node == LDP_IPV4_NODE
523 || saved_node == LDP_IPV6_NODE)
524 && (tried == 1)) {
525 vtysh_execute("exit-address-family");
526 } else if ((saved_node == BGP_EVPN_VNI_NODE) && (tried == 1)) {
527 vtysh_execute("exit-vni");
528 } else if (saved_node == BGP_VRF_POLICY_NODE && (tried == 1)) {
529 vtysh_execute("exit-vrf-policy");
530 } else if ((saved_node == BGP_VNC_DEFAULTS_NODE
531 || saved_node == BGP_VNC_NVE_GROUP_NODE
532 || saved_node == BGP_VNC_L2_GROUP_NODE)
533 && (tried == 1)) {
534 vtysh_execute("exit-vnc");
535 } else if (saved_node == VRF_NODE && (tried == 1)) {
536 vtysh_execute("exit-vrf");
537 } else if ((saved_node == KEYCHAIN_KEY_NODE
538 || saved_node == LDP_PSEUDOWIRE_NODE
539 || saved_node == LDP_IPV4_IFACE_NODE
540 || saved_node == LDP_IPV6_IFACE_NODE)
541 && (tried == 1)) {
542 vtysh_execute("exit");
543 } else if ((saved_node == SR_SEGMENT_LIST_NODE
544 || saved_node == SR_POLICY_NODE
545 || saved_node == SR_CANDIDATE_DYN_NODE
546 || saved_node == PCEP_NODE
547 || saved_node == PCEP_PCE_CONFIG_NODE
548 || saved_node == PCEP_PCE_NODE
549 || saved_node == PCEP_PCC_NODE)
550 && (tried > 0)) {
551 vtysh_execute("exit");
552 } else if (tried) {
553 vtysh_execute("end");
554 vtysh_execute("configure");
555 }
556 }
557 /*
558 * If command didn't succeed in any node, continue with return value
559 * from first try.
560 */
561 else if (tried) {
562 ret = saved_ret;
563 }
564
565 cmd_free_strvec(vline);
566
567 cmd_stat = ret;
568 switch (ret) {
569 case CMD_WARNING:
570 case CMD_WARNING_CONFIG_FAILED:
571 if (vty->type == VTY_FILE)
572 vty_out(vty, "Warning...\n");
573 break;
574 case CMD_ERR_AMBIGUOUS:
575 vty_out(vty, "%% Ambiguous command: %s\n", line);
576 break;
577 case CMD_ERR_NO_MATCH:
578 vty_out(vty, "%% Unknown command: %s\n", line);
579 break;
580 case CMD_ERR_INCOMPLETE:
581 vty_out(vty, "%% Command incomplete: %s\n", line);
582 break;
583 case CMD_SUCCESS_DAEMON: {
584 /*
585 * FIXME: Don't open pager for exit commands. popen() causes
586 * problems if exited from vtysh at all. This hack shouldn't
587 * cause any problem but is really ugly.
588 */
589 if (pager && strncmp(line, "exit", 4))
590 vty_open_pager(vty);
591
592 if (!strcmp(cmd->string, "configure")) {
593 for (i = 0; i < array_size(vtysh_client); i++) {
594 cmd_stat = vtysh_client_execute(
595 &vtysh_client[i], line);
596 if (cmd_stat == CMD_WARNING)
597 break;
598 }
599
600 if (cmd_stat) {
601 line = "end";
602 vline = cmd_make_strvec(line);
603
604
605 if (vline == NULL) {
606 if (vty->is_paged)
607 vty_close_pager(vty);
608 return CMD_SUCCESS;
609 }
610
611 ret = cmd_execute_command(vline, vty, &cmd, 1);
612 cmd_free_strvec(vline);
613 if (ret != CMD_SUCCESS_DAEMON)
614 break;
615 } else if (cmd->func) {
616 (*cmd->func)(cmd, vty, 0, NULL);
617 break;
618 }
619 }
620
621 cmd_stat = CMD_SUCCESS;
622 struct vtysh_client *vc;
623 for (i = 0; i < array_size(vtysh_client); i++) {
624 if (cmd->daemon & vtysh_client[i].flag) {
625 if (vtysh_client[i].fd < 0
626 && (cmd->daemon == vtysh_client[i].flag)) {
627 for (vc = &vtysh_client[i]; vc;
628 vc = vc->next)
629 if (vc->fd == VTYSH_WAS_ACTIVE)
630 vtysh_reconnect(vc);
631 }
632 if (vtysh_client[i].fd < 0
633 && (cmd->daemon == vtysh_client[i].flag)) {
634 bool any_inst = false;
635 for (vc = &vtysh_client[i]; vc;
636 vc = vc->next)
637 any_inst = any_inst
638 || (vc->fd > 0);
639 if (!any_inst) {
640 fprintf(stderr,
641 "%s is not running\n",
642 vtysh_client[i].name);
643 continue;
644 }
645 }
646 cmd_stat = vtysh_client_execute(
647 &vtysh_client[i], line);
648 if (cmd_stat != CMD_SUCCESS)
649 break;
650 }
651 }
652 if (cmd_stat != CMD_SUCCESS)
653 break;
654
655 if (cmd->func)
656 (*cmd->func)(cmd, vty, 0, NULL);
657 }
658 }
659 if (vty->is_paged)
660 vty_close_pager(vty);
661
662 return cmd_stat;
663 }
664
665 int vtysh_execute_no_pager(const char *line)
666 {
667 return vtysh_execute_func(line, 0);
668 }
669
670 int vtysh_execute(const char *line)
671 {
672 return vtysh_execute_func(line, 1);
673 }
674
675 static char *trim(char *s)
676 {
677 size_t size;
678 char *end;
679
680 size = strlen(s);
681
682 if (!size)
683 return s;
684
685 end = s + size - 1;
686 while (end >= s && isspace((unsigned char)*end))
687 end--;
688 *(end + 1) = '\0';
689
690 while (*s && isspace((unsigned char)*s))
691 s++;
692
693 return s;
694 }
695
696 int vtysh_mark_file(const char *filename)
697 {
698 struct vty *vty;
699 FILE *confp = NULL;
700 int ret;
701 vector vline;
702 int tried = 0;
703 bool ending;
704 const struct cmd_element *cmd;
705 int saved_ret, prev_node;
706 int lineno = 0;
707 char *vty_buf_copy = NULL;
708 char *vty_buf_trimmed = NULL;
709
710 if (strncmp("-", filename, 1) == 0)
711 confp = stdin;
712 else
713 confp = fopen(filename, "r");
714
715 if (confp == NULL) {
716 fprintf(stderr, "%% Can't open config file %s due to '%s'.\n",
717 filename, safe_strerror(errno));
718 return CMD_ERR_NO_FILE;
719 }
720
721 vty = vty_new();
722 vty->wfd = STDOUT_FILENO;
723 vty->type = VTY_TERM;
724 vty->node = CONFIG_NODE;
725
726 vtysh_execute_no_pager("enable");
727 vtysh_execute_no_pager("configure");
728 vty_buf_copy = XCALLOC(MTYPE_VTYSH_CMD, VTY_BUFSIZ);
729
730 while (fgets(vty->buf, VTY_BUFSIZ, confp)) {
731 lineno++;
732 tried = 0;
733 strlcpy(vty_buf_copy, vty->buf, VTY_BUFSIZ);
734 vty_buf_trimmed = trim(vty_buf_copy);
735
736 switch (vty->node) {
737 case LDP_IPV4_IFACE_NODE:
738 if (strncmp(vty_buf_copy, " ", 3)) {
739 vty_out(vty, " exit-ldp-if\n");
740 vty->node = LDP_IPV4_NODE;
741 }
742 break;
743 case LDP_IPV6_IFACE_NODE:
744 if (strncmp(vty_buf_copy, " ", 3)) {
745 vty_out(vty, " exit-ldp-if\n");
746 vty->node = LDP_IPV6_NODE;
747 }
748 break;
749 case LDP_PSEUDOWIRE_NODE:
750 if (strncmp(vty_buf_copy, " ", 2)) {
751 vty_out(vty, " exit\n");
752 vty->node = LDP_L2VPN_NODE;
753 }
754 break;
755 case SR_CANDIDATE_DYN_NODE:
756 if (strncmp(vty_buf_copy, " ", 2)) {
757 vty_out(vty, " exit\n");
758 vty->node = SR_POLICY_NODE;
759 }
760 break;
761 default:
762 break;
763 }
764
765 if (vty_buf_trimmed[0] == '!' || vty_buf_trimmed[0] == '#') {
766 vty_out(vty, "%s", vty->buf);
767 continue;
768 }
769
770 /* Split readline string up into the vector. */
771 vline = cmd_make_strvec(vty->buf);
772
773 if (vline == NULL) {
774 vty_out(vty, "%s", vty->buf);
775 continue;
776 }
777
778 /*
779 * Ignore the "end" lines, we will generate these where
780 * appropriate
781 */
782 if (strlen(vty_buf_trimmed) == 3
783 && strncmp("end", vty_buf_trimmed, 3) == 0) {
784 cmd_free_strvec(vline);
785 continue;
786 }
787
788 prev_node = vty->node;
789 saved_ret = ret = cmd_execute_command_strict(vline, vty, &cmd);
790
791 /*
792 * If command doesn't succeeded in current node, try to walk up
793 * in node tree. Changing vty->node is enough to try it just
794 * out without actual walkup in the vtysh.
795 */
796 while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON
797 && ret != CMD_WARNING && ret != CMD_WARNING_CONFIG_FAILED
798 && ret != CMD_ERR_AMBIGUOUS && ret != CMD_ERR_INCOMPLETE
799 && vty->node > CONFIG_NODE) {
800 vty->node = node_parent(vty->node);
801 ret = cmd_execute_command_strict(vline, vty, &cmd);
802 tried++;
803 }
804
805 /*
806 * If command succeeded in any other node than current (tried >
807 * 0) we have to move into node in the vtysh where it
808 * succeeded.
809 */
810 if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON
811 || ret == CMD_WARNING) {
812 if ((prev_node == BGP_VPNV4_NODE
813 || prev_node == BGP_VPNV6_NODE
814 || prev_node == BGP_IPV4_NODE
815 || prev_node == BGP_IPV6_NODE
816 || prev_node == BGP_FLOWSPECV4_NODE
817 || prev_node == BGP_FLOWSPECV6_NODE
818 || prev_node == BGP_IPV4L_NODE
819 || prev_node == BGP_IPV6L_NODE
820 || prev_node == BGP_IPV4M_NODE
821 || prev_node == BGP_IPV6M_NODE
822 || prev_node == BGP_EVPN_NODE)
823 && (tried == 1)) {
824 vty_out(vty, "exit-address-family\n");
825 } else if ((prev_node == BGP_EVPN_VNI_NODE)
826 && (tried == 1)) {
827 vty_out(vty, "exit-vni\n");
828 } else if ((prev_node == KEYCHAIN_KEY_NODE)
829 && (tried == 1)) {
830 vty_out(vty, "exit\n");
831 } else if ((prev_node == BFD_PEER_NODE)
832 && (tried == 1)) {
833 vty_out(vty, "exit\n");
834 } else if (((prev_node == SEGMENT_ROUTING_NODE)
835 || (prev_node == SR_TRAFFIC_ENG_NODE)
836 || (prev_node == SR_SEGMENT_LIST_NODE)
837 || (prev_node == SR_POLICY_NODE)
838 || (prev_node == SR_CANDIDATE_DYN_NODE)
839 || (prev_node == PCEP_NODE)
840 || (prev_node == PCEP_PCE_CONFIG_NODE)
841 || (prev_node == PCEP_PCE_NODE)
842 || (prev_node == PCEP_PCC_NODE))
843 && (tried > 0)) {
844 ending = (vty->node != SEGMENT_ROUTING_NODE)
845 && (vty->node != SR_TRAFFIC_ENG_NODE)
846 && (vty->node != SR_SEGMENT_LIST_NODE)
847 && (vty->node != SR_POLICY_NODE)
848 && (vty->node != SR_CANDIDATE_DYN_NODE)
849 && (vty->node != PCEP_NODE)
850 && (vty->node != PCEP_PCE_CONFIG_NODE)
851 && (vty->node != PCEP_PCE_NODE)
852 && (vty->node != PCEP_PCC_NODE);
853 if (ending)
854 tried--;
855 while (tried-- > 0)
856 vty_out(vty, "exit\n");
857 if (ending)
858 vty_out(vty, "end\n");
859 } else if (tried) {
860 vty_out(vty, "end\n");
861 }
862 }
863 /*
864 * If command didn't succeed in any node, continue with return
865 * value from first try.
866 */
867 else if (tried) {
868 ret = saved_ret;
869 vty->node = prev_node;
870 }
871
872 cmd_free_strvec(vline);
873 switch (ret) {
874 case CMD_WARNING:
875 case CMD_WARNING_CONFIG_FAILED:
876 if (vty->type == VTY_FILE)
877 fprintf(stderr, "line %d: Warning...: %s\n",
878 lineno, vty->buf);
879 fclose(confp);
880 vty_close(vty);
881 XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
882 return ret;
883 case CMD_ERR_AMBIGUOUS:
884 fprintf(stderr, "line %d: %% Ambiguous command: %s\n",
885 lineno, vty->buf);
886 fclose(confp);
887 vty_close(vty);
888 XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
889 return CMD_ERR_AMBIGUOUS;
890 case CMD_ERR_NO_MATCH:
891 fprintf(stderr, "line %d: %% Unknown command: %s\n",
892 lineno, vty->buf);
893 fclose(confp);
894 vty_close(vty);
895 XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
896 return CMD_ERR_NO_MATCH;
897 case CMD_ERR_INCOMPLETE:
898 fprintf(stderr, "line %d: %% Command incomplete: %s\n",
899 lineno, vty->buf);
900 fclose(confp);
901 vty_close(vty);
902 XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
903 return CMD_ERR_INCOMPLETE;
904 case CMD_SUCCESS:
905 vty_out(vty, "%s", vty->buf);
906 if (strmatch(vty_buf_trimmed, "exit-vrf"))
907 vty_out(vty, "end\n");
908 break;
909 case CMD_SUCCESS_DAEMON: {
910 int cmd_stat;
911
912 vty_out(vty, "%s", vty->buf);
913 if (strmatch(vty_buf_trimmed, "exit-vrf"))
914 vty_out(vty, "end\n");
915 cmd_stat = vtysh_client_execute(&vtysh_client[0],
916 vty->buf);
917 if (cmd_stat != CMD_SUCCESS)
918 break;
919
920 if (cmd->func)
921 (*cmd->func)(cmd, vty, 0, NULL);
922 }
923 }
924 }
925 /* This is the end */
926 vty_out(vty, "\nend\n");
927 vty_close(vty);
928 XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
929
930 if (confp != stdin)
931 fclose(confp);
932
933 return 0;
934 }
935
936 /* Configration make from file. */
937 int vtysh_config_from_file(struct vty *vty, FILE *fp)
938 {
939 int ret;
940 const struct cmd_element *cmd;
941 int lineno = 0;
942 /* once we have an error, we remember & return that */
943 int retcode = CMD_SUCCESS;
944
945 while (fgets(vty->buf, VTY_BUFSIZ, fp)) {
946 lineno++;
947
948 ret = command_config_read_one_line(vty, &cmd, lineno, 1);
949
950 switch (ret) {
951 case CMD_WARNING:
952 case CMD_WARNING_CONFIG_FAILED:
953 if (vty->type == VTY_FILE)
954 fprintf(stderr, "line %d: Warning[%d]...: %s\n",
955 lineno, vty->node, vty->buf);
956 retcode = ret;
957
958 break;
959 case CMD_ERR_AMBIGUOUS:
960 fprintf(stderr,
961 "line %d: %% Ambiguous command[%d]: %s\n",
962 lineno, vty->node, vty->buf);
963 retcode = CMD_ERR_AMBIGUOUS;
964 break;
965 case CMD_ERR_NO_MATCH:
966 fprintf(stderr, "line %d: %% Unknown command[%d]: %s",
967 lineno, vty->node, vty->buf);
968 retcode = CMD_ERR_NO_MATCH;
969 break;
970 case CMD_ERR_INCOMPLETE:
971 fprintf(stderr,
972 "line %d: %% Command incomplete[%d]: %s\n",
973 lineno, vty->node, vty->buf);
974 retcode = CMD_ERR_INCOMPLETE;
975 break;
976 case CMD_SUCCESS_DAEMON: {
977 unsigned int i;
978 int cmd_stat = CMD_SUCCESS;
979
980 for (i = 0; i < array_size(vtysh_client); i++) {
981 if (cmd->daemon & vtysh_client[i].flag) {
982 cmd_stat = vtysh_client_execute(
983 &vtysh_client[i], vty->buf);
984 /*
985 * CMD_WARNING - Can mean that the
986 * command was parsed successfully but
987 * it was already entered in a few
988 * spots. As such if we receive a
989 * CMD_WARNING from a daemon we
990 * shouldn't stop talking to the other
991 * daemons for the particular command.
992 */
993 if (cmd_stat != CMD_SUCCESS
994 && cmd_stat != CMD_WARNING) {
995 fprintf(stderr,
996 "line %d: Failure to communicate[%d] to %s, line: %s\n",
997 lineno, cmd_stat,
998 vtysh_client[i].name,
999 vty->buf);
1000 retcode = cmd_stat;
1001 break;
1002 }
1003 }
1004 }
1005 if (cmd_stat != CMD_SUCCESS)
1006 break;
1007
1008 if (cmd->func)
1009 (*cmd->func)(cmd, vty, 0, NULL);
1010 }
1011 }
1012 }
1013
1014 return (retcode);
1015 }
1016
1017 /*
1018 * Function processes cli commands terminated with '?' character when entered
1019 * through either 'vtysh' or 'vtysh -c' interfaces.
1020 */
1021 static int vtysh_process_questionmark(const char *input, int input_len)
1022 {
1023 int ret, width = 0;
1024 unsigned int i;
1025 vector vline, describe;
1026 struct cmd_token *token;
1027
1028 if (!input)
1029 return 1;
1030
1031 vline = cmd_make_strvec(input);
1032
1033 /* In case of '> ?'. */
1034 if (vline == NULL) {
1035 vline = vector_init(1);
1036 vector_set(vline, NULL);
1037 } else if (input_len && isspace((unsigned char)input[input_len - 1]))
1038 vector_set(vline, NULL);
1039
1040 describe = cmd_describe_command(vline, vty, &ret);
1041
1042 /* Ambiguous and no match error. */
1043 switch (ret) {
1044 case CMD_ERR_AMBIGUOUS:
1045 cmd_free_strvec(vline);
1046 vector_free(describe);
1047 vty_out(vty, "%% Ambiguous command.\n");
1048 rl_on_new_line();
1049 return 0;
1050 case CMD_ERR_NO_MATCH:
1051 cmd_free_strvec(vline);
1052 if (describe)
1053 vector_free(describe);
1054 vty_out(vty, "%% There is no matched command.\n");
1055 rl_on_new_line();
1056 return 0;
1057 }
1058
1059 /* Get width of command string. */
1060 width = 0;
1061 for (i = 0; i < vector_active(describe); i++)
1062 if ((token = vector_slot(describe, i)) != NULL) {
1063 if (token->text[0] == '\0')
1064 continue;
1065
1066 int len = strlen(token->text);
1067
1068 if (width < len)
1069 width = len;
1070 }
1071
1072 for (i = 0; i < vector_active(describe); i++)
1073 if ((token = vector_slot(describe, i)) != NULL) {
1074 if (!token->desc)
1075 vty_out(vty, " %-s\n", token->text);
1076 else
1077 vty_out(vty, " %-*s %s\n", width, token->text,
1078 token->desc);
1079
1080 if (IS_VARYING_TOKEN(token->type)) {
1081 const char *ref = vector_slot(
1082 vline, vector_active(vline) - 1);
1083
1084 vector varcomps = vector_init(VECTOR_MIN_SIZE);
1085 cmd_variable_complete(token, ref, varcomps);
1086
1087 if (vector_active(varcomps) > 0) {
1088 int rows, cols;
1089 rl_get_screen_size(&rows, &cols);
1090
1091 char *ac = cmd_variable_comp2str(
1092 varcomps, cols);
1093 vty_out(vty, "%s\n", ac);
1094 XFREE(MTYPE_TMP, ac);
1095 }
1096
1097 vector_free(varcomps);
1098 }
1099 }
1100
1101 cmd_free_strvec(vline);
1102 vector_free(describe);
1103
1104 return 0;
1105 }
1106
1107 /*
1108 * Entry point for user commands terminated with '?' character and typed through
1109 * the usual vtysh's stdin interface. This is the function being registered with
1110 * readline() api's.
1111 */
1112 static int vtysh_rl_describe(int a, int b)
1113 {
1114 int ret;
1115
1116 vty_out(vty, "\n");
1117
1118 ret = vtysh_process_questionmark(rl_line_buffer, rl_end);
1119 rl_on_new_line();
1120
1121 return ret;
1122 }
1123
1124 /*
1125 * Function in charged of processing vtysh instructions terminating with '?'
1126 * character and received through the 'vtysh -c' interface. If user's
1127 * instruction is well-formatted, we will call the same processing routine
1128 * utilized by the traditional vtysh's stdin interface.
1129 */
1130 int vtysh_execute_command_questionmark(char *input)
1131 {
1132 int input_len, qmark_count = 0;
1133 const char *str;
1134
1135 if (!(input && *input))
1136 return 1;
1137
1138 /* Finding out question_mark count and strlen */
1139 for (str = input; *str; ++str) {
1140 if (*str == '?')
1141 qmark_count++;
1142 }
1143 input_len = str - input;
1144
1145 /*
1146 * Verify that user's input terminates in '?' and that patterns such as
1147 * 'cmd ? subcmd ?' are prevented.
1148 */
1149 if (qmark_count != 1 || input[input_len - 1] != '?')
1150 return 1;
1151
1152 /*
1153 * Questionmark-processing function is not expecting to receive '?'
1154 * character in input string.
1155 */
1156 input[input_len - 1] = '\0';
1157
1158 return vtysh_process_questionmark(input, input_len - 1);
1159 }
1160
1161 /* Result of cmd_complete_command() call will be stored here
1162 * and used in new_completion() in order to put the space in
1163 * correct places only. */
1164 int complete_status;
1165
1166 static char *command_generator(const char *text, int state)
1167 {
1168 vector vline;
1169 static char **matched = NULL;
1170 static int index = 0;
1171
1172 /* First call. */
1173 if (!state) {
1174 index = 0;
1175
1176 if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
1177 return NULL;
1178
1179 vline = cmd_make_strvec(rl_line_buffer);
1180 if (vline == NULL)
1181 return NULL;
1182
1183 if (rl_end &&
1184 isspace((unsigned char)rl_line_buffer[rl_end - 1]))
1185 vector_set(vline, NULL);
1186
1187 matched = cmd_complete_command(vline, vty, &complete_status);
1188 cmd_free_strvec(vline);
1189 }
1190
1191 if (matched && matched[index]) {
1192 XCOUNTFREE(MTYPE_COMPLETION, matched[index]);
1193 return matched[index++];
1194 }
1195
1196 XFREE(MTYPE_TMP, matched);
1197
1198 return NULL;
1199 }
1200
1201 static char **new_completion(const char *text, int start, int end)
1202 {
1203 char **matches;
1204
1205 matches = rl_completion_matches(text, command_generator);
1206
1207 if (matches) {
1208 rl_point = rl_end;
1209 if (complete_status != CMD_COMPLETE_FULL_MATCH)
1210 /* only append a space on full match */
1211 rl_completion_append_character = '\0';
1212 }
1213
1214 return matches;
1215 }
1216
1217 /* Vty node structures. */
1218 #ifdef HAVE_BGPD
1219 static struct cmd_node bgp_node = {
1220 .name = "bgp",
1221 .node = BGP_NODE,
1222 .parent_node = CONFIG_NODE,
1223 .prompt = "%s(config-router)# ",
1224 };
1225 #endif /* HAVE_BGPD */
1226
1227 static struct cmd_node rip_node = {
1228 .name = "rip",
1229 .node = RIP_NODE,
1230 .parent_node = CONFIG_NODE,
1231 .prompt = "%s(config-router)# ",
1232 };
1233
1234 #ifdef HAVE_ISISD
1235 static struct cmd_node isis_node = {
1236 .name = "isis",
1237 .node = ISIS_NODE,
1238 .parent_node = CONFIG_NODE,
1239 .prompt = "%s(config-router)# ",
1240 };
1241 #endif /* HAVE_ISISD */
1242
1243 #ifdef HAVE_FABRICD
1244 static struct cmd_node openfabric_node = {
1245 .name = "openfabric",
1246 .node = OPENFABRIC_NODE,
1247 .parent_node = CONFIG_NODE,
1248 .prompt = "%s(config-router)# ",
1249 };
1250 #endif /* HAVE_FABRICD */
1251
1252 static struct cmd_node interface_node = {
1253 .name = "interface",
1254 .node = INTERFACE_NODE,
1255 .parent_node = CONFIG_NODE,
1256 .prompt = "%s(config-if)# ",
1257 };
1258
1259 static struct cmd_node pw_node = {
1260 .name = "pw",
1261 .node = PW_NODE,
1262 .parent_node = CONFIG_NODE,
1263 .prompt = "%s(config-pw)# ",
1264 };
1265
1266 static struct cmd_node segment_routing_node = {
1267 .name = "segment-routing",
1268 .node = SEGMENT_ROUTING_NODE,
1269 .parent_node = CONFIG_NODE,
1270 .prompt = "%s(config-sr)# ",
1271 };
1272
1273 #if defined(HAVE_PATHD)
1274 static struct cmd_node sr_traffic_eng_node = {
1275 .name = "sr traffic-eng",
1276 .node = SR_TRAFFIC_ENG_NODE,
1277 .parent_node = SEGMENT_ROUTING_NODE,
1278 .prompt = "%s(config-sr-te)# ",
1279 };
1280
1281 static struct cmd_node srte_segment_list_node = {
1282 .name = "srte segment-list",
1283 .node = SR_SEGMENT_LIST_NODE,
1284 .parent_node = SR_TRAFFIC_ENG_NODE,
1285 .prompt = "%s(config-sr-te-segment-list)# ",
1286 };
1287
1288 static struct cmd_node srte_policy_node = {
1289 .name = "srte policy",
1290 .node = SR_POLICY_NODE,
1291 .parent_node = SR_TRAFFIC_ENG_NODE,
1292 .prompt = "%s(config-sr-te-policy)# ",
1293 };
1294
1295 static struct cmd_node srte_candidate_dyn_node = {
1296 .name = "srte candidate-dyn",
1297 .node = SR_CANDIDATE_DYN_NODE,
1298 .parent_node = SR_POLICY_NODE,
1299 .prompt = "%s(config-sr-te-candidate)# ",
1300 };
1301
1302 #if defined(HAVE_PATHD_PCEP)
1303 static struct cmd_node pcep_node = {
1304 .name = "srte pcep",
1305 .node = PCEP_NODE,
1306 .parent_node = SR_TRAFFIC_ENG_NODE,
1307 .prompt = "%s(config-sr-te-pcep)# "
1308 };
1309
1310 static struct cmd_node pcep_pcc_node = {
1311 .name = "srte pcep pcc",
1312 .node = PCEP_PCC_NODE,
1313 .parent_node = PCEP_NODE,
1314 .prompt = "%s(config-sr-te-pcep-pcc)# ",
1315 };
1316
1317 static struct cmd_node pcep_pce_node = {
1318 .name = "srte pcep pce-peer",
1319 .node = PCEP_PCE_NODE,
1320 .parent_node = PCEP_NODE,
1321 .prompt = "%s(config-sr-te-pcep-pce-peer)# ",
1322 };
1323
1324 static struct cmd_node pcep_pce_config_node = {
1325 .name = "srte pcep pce-config",
1326 .node = PCEP_PCE_CONFIG_NODE,
1327 .parent_node = PCEP_NODE,
1328 .prompt = "%s(pcep-sr-te-pcep-pce-config)# ",
1329 };
1330 #endif /* HAVE_PATHD_PCEP */
1331 #endif /* HAVE_PATHD */
1332
1333 static struct cmd_node vrf_node = {
1334 .name = "vrf",
1335 .node = VRF_NODE,
1336 .parent_node = CONFIG_NODE,
1337 .prompt = "%s(config-vrf)# ",
1338 };
1339
1340 static struct cmd_node nh_group_node = {
1341 .name = "nexthop-group",
1342 .node = NH_GROUP_NODE,
1343 .parent_node = CONFIG_NODE,
1344 .prompt = "%s(config-nh-group)# ",
1345 };
1346
1347 static struct cmd_node rmap_node = {
1348 .name = "routemap",
1349 .node = RMAP_NODE,
1350 .parent_node = CONFIG_NODE,
1351 .prompt = "%s(config-route-map)# ",
1352 };
1353
1354 static struct cmd_node srv6_node = {
1355 .name = "srv6",
1356 .node = SRV6_NODE,
1357 .parent_node = SEGMENT_ROUTING_NODE,
1358 .prompt = "%s(config-srv6)# ",
1359 };
1360
1361 static struct cmd_node srv6_locs_node = {
1362 .name = "srv6-locators",
1363 .node = SRV6_LOCS_NODE,
1364 .parent_node = SRV6_NODE,
1365 .prompt = "%s(config-srv6-locators)# ",
1366 };
1367
1368 static struct cmd_node srv6_loc_node = {
1369 .name = "srv6-locator",
1370 .node = SRV6_LOC_NODE,
1371 .parent_node = SRV6_LOCS_NODE,
1372 .prompt = "%s(config-srv6-locator)# ",
1373 };
1374
1375 #ifdef HAVE_PBRD
1376 static struct cmd_node pbr_map_node = {
1377 .name = "pbr-map",
1378 .node = PBRMAP_NODE,
1379 .parent_node = CONFIG_NODE,
1380 .prompt = "%s(config-pbr-map)# ",
1381 };
1382 #endif /* HAVE_PBRD */
1383
1384 static struct cmd_node zebra_node = {
1385 .name = "zebra",
1386 .node = ZEBRA_NODE,
1387 .parent_node = CONFIG_NODE,
1388 .prompt = "%s(config-router)# ",
1389 };
1390
1391 #ifdef HAVE_BGPD
1392 static struct cmd_node bgp_vpnv4_node = {
1393 .name = "bgp vpnv4",
1394 .node = BGP_VPNV4_NODE,
1395 .parent_node = BGP_NODE,
1396 .prompt = "%s(config-router-af)# ",
1397 };
1398
1399 static struct cmd_node bgp_vpnv6_node = {
1400 .name = "bgp vpnv6",
1401 .node = BGP_VPNV6_NODE,
1402 .parent_node = BGP_NODE,
1403 .prompt = "%s(config-router-af)# ",
1404 };
1405
1406 static struct cmd_node bgp_flowspecv4_node = {
1407 .name = "bgp ipv4 flowspec",
1408 .node = BGP_FLOWSPECV4_NODE,
1409 .parent_node = BGP_NODE,
1410 .prompt = "%s(config-router-af)# ",
1411 };
1412
1413 static struct cmd_node bgp_flowspecv6_node = {
1414 .name = "bgp ipv6 flowspec",
1415 .node = BGP_FLOWSPECV6_NODE,
1416 .parent_node = BGP_NODE,
1417 .prompt = "%s(config-router-af)# ",
1418 };
1419
1420 static struct cmd_node bgp_ipv4_node = {
1421 .name = "bgp ipv4 unicast",
1422 .node = BGP_IPV4_NODE,
1423 .parent_node = BGP_NODE,
1424 .prompt = "%s(config-router-af)# ",
1425 };
1426
1427 static struct cmd_node bgp_ipv4m_node = {
1428 .name = "bgp ipv4 multicast",
1429 .node = BGP_IPV4M_NODE,
1430 .parent_node = BGP_NODE,
1431 .prompt = "%s(config-router-af)# ",
1432 };
1433
1434 static struct cmd_node bgp_ipv4l_node = {
1435 .name = "bgp ipv4 labeled unicast",
1436 .node = BGP_IPV4L_NODE,
1437 .parent_node = BGP_NODE,
1438 .prompt = "%s(config-router-af)# ",
1439 };
1440
1441 static struct cmd_node bgp_ipv6_node = {
1442 .name = "bgp ipv6",
1443 .node = BGP_IPV6_NODE,
1444 .parent_node = BGP_NODE,
1445 .prompt = "%s(config-router-af)# ",
1446 };
1447
1448 static struct cmd_node bgp_ipv6m_node = {
1449 .name = "bgp ipv6 multicast",
1450 .node = BGP_IPV6M_NODE,
1451 .parent_node = BGP_NODE,
1452 .prompt = "%s(config-router-af)# ",
1453 };
1454
1455 static struct cmd_node bgp_evpn_node = {
1456 .name = "bgp evpn",
1457 .node = BGP_EVPN_NODE,
1458 .parent_node = BGP_NODE,
1459 .prompt = "%s(config-router-af)# ",
1460 };
1461
1462 static struct cmd_node bgp_evpn_vni_node = {
1463 .name = "bgp evpn vni",
1464 .node = BGP_EVPN_VNI_NODE,
1465 .parent_node = BGP_EVPN_NODE,
1466 .prompt = "%s(config-router-af-vni)# ",
1467 };
1468
1469 static struct cmd_node bgp_ipv6l_node = {
1470 .name = "bgp ipv6 labeled unicast",
1471 .node = BGP_IPV6L_NODE,
1472 .parent_node = BGP_NODE,
1473 .prompt = "%s(config-router-af)# ",
1474 };
1475
1476 #ifdef ENABLE_BGP_VNC
1477 static struct cmd_node bgp_vnc_defaults_node = {
1478 .name = "bgp vnc defaults",
1479 .node = BGP_VNC_DEFAULTS_NODE,
1480 .parent_node = BGP_NODE,
1481 .prompt = "%s(config-router-vnc-defaults)# ",
1482 };
1483
1484 static struct cmd_node bgp_vnc_nve_group_node = {
1485 .name = "bgp vnc nve",
1486 .node = BGP_VNC_NVE_GROUP_NODE,
1487 .parent_node = BGP_NODE,
1488 .prompt = "%s(config-router-vnc-nve-group)# ",
1489 };
1490
1491 static struct cmd_node bgp_vrf_policy_node = {
1492 .name = "bgp vrf policy",
1493 .node = BGP_VRF_POLICY_NODE,
1494 .parent_node = BGP_NODE,
1495 .prompt = "%s(config-router-vrf-policy)# ",
1496 };
1497
1498 static struct cmd_node bgp_vnc_l2_group_node = {
1499 .name = "bgp vnc l2",
1500 .node = BGP_VNC_L2_GROUP_NODE,
1501 .parent_node = BGP_NODE,
1502 .prompt = "%s(config-router-vnc-l2-group)# ",
1503 };
1504 #endif /* ENABLE_BGP_VNC */
1505
1506 static struct cmd_node bmp_node = {
1507 .name = "bmp",
1508 .node = BMP_NODE,
1509 .parent_node = BGP_NODE,
1510 .prompt = "%s(config-bgp-bmp)# "
1511 };
1512
1513 static struct cmd_node bgp_srv6_node = {
1514 .name = "bgp srv6",
1515 .node = BGP_SRV6_NODE,
1516 .parent_node = BGP_NODE,
1517 .prompt = "%s(config-router-srv6)# ",
1518 };
1519 #endif /* HAVE_BGPD */
1520
1521 #ifdef HAVE_OSPFD
1522 static struct cmd_node ospf_node = {
1523 .name = "ospf",
1524 .node = OSPF_NODE,
1525 .parent_node = CONFIG_NODE,
1526 .prompt = "%s(config-router)# ",
1527 };
1528 #endif /* HAVE_OSPFD */
1529
1530 #ifdef HAVE_EIGRPD
1531 static struct cmd_node eigrp_node = {
1532 .name = "eigrp",
1533 .node = EIGRP_NODE,
1534 .parent_node = CONFIG_NODE,
1535 .prompt = "%s(config-router)# ",
1536 };
1537 #endif /* HAVE_EIGRPD */
1538
1539 #ifdef HAVE_BABELD
1540 static struct cmd_node babel_node = {
1541 .name = "babel",
1542 .node = BABEL_NODE,
1543 .parent_node = CONFIG_NODE,
1544 .prompt = "%s(config-router)# ",
1545 };
1546 #endif /* HAVE_BABELD */
1547
1548 static struct cmd_node ripng_node = {
1549 .name = "ripng",
1550 .node = RIPNG_NODE,
1551 .parent_node = CONFIG_NODE,
1552 .prompt = "%s(config-router)# ",
1553 };
1554
1555 #ifdef HAVE_OSPF6D
1556 static struct cmd_node ospf6_node = {
1557 .name = "ospf6",
1558 .node = OSPF6_NODE,
1559 .parent_node = CONFIG_NODE,
1560 .prompt = "%s(config-ospf6)# ",
1561 };
1562 #endif /* HAVE_OSPF6D */
1563
1564 #ifdef HAVE_LDPD
1565 static struct cmd_node ldp_node = {
1566 .name = "ldp",
1567 .node = LDP_NODE,
1568 .parent_node = CONFIG_NODE,
1569 .prompt = "%s(config-ldp)# ",
1570 };
1571
1572 static struct cmd_node ldp_ipv4_node = {
1573 .name = "ldp ipv4",
1574 .node = LDP_IPV4_NODE,
1575 .parent_node = LDP_NODE,
1576 .prompt = "%s(config-ldp-af)# ",
1577 };
1578
1579 static struct cmd_node ldp_ipv6_node = {
1580 .name = "ldp ipv6",
1581 .node = LDP_IPV6_NODE,
1582 .parent_node = LDP_NODE,
1583 .prompt = "%s(config-ldp-af)# ",
1584 };
1585
1586 static struct cmd_node ldp_ipv4_iface_node = {
1587 .name = "ldp ipv4 interface",
1588 .node = LDP_IPV4_IFACE_NODE,
1589 .parent_node = LDP_IPV4_NODE,
1590 .prompt = "%s(config-ldp-af-if)# ",
1591 };
1592
1593 static struct cmd_node ldp_ipv6_iface_node = {
1594 .name = "ldp ipv6 interface",
1595 .node = LDP_IPV6_IFACE_NODE,
1596 .parent_node = LDP_IPV6_NODE,
1597 .prompt = "%s(config-ldp-af-if)# ",
1598 };
1599
1600 static struct cmd_node ldp_l2vpn_node = {
1601 .name = "ldp l2vpn",
1602 .node = LDP_L2VPN_NODE,
1603 .parent_node = CONFIG_NODE,
1604 .prompt = "%s(config-l2vpn)# ",
1605 };
1606
1607 static struct cmd_node ldp_pseudowire_node = {
1608 .name = "ldp",
1609 .node = LDP_PSEUDOWIRE_NODE,
1610 .parent_node = LDP_L2VPN_NODE,
1611 .prompt = "%s(config-l2vpn-pw)# ",
1612 };
1613 #endif /* HAVE_LDPD */
1614
1615 static struct cmd_node keychain_node = {
1616 .name = "keychain",
1617 .node = KEYCHAIN_NODE,
1618 .parent_node = CONFIG_NODE,
1619 .prompt = "%s(config-keychain)# ",
1620 };
1621
1622 static struct cmd_node keychain_key_node = {
1623 .name = "keychain key",
1624 .node = KEYCHAIN_KEY_NODE,
1625 .parent_node = KEYCHAIN_NODE,
1626 .prompt = "%s(config-keychain-key)# ",
1627 };
1628
1629 struct cmd_node link_params_node = {
1630 .name = "link-params",
1631 .node = LINK_PARAMS_NODE,
1632 .parent_node = INTERFACE_NODE,
1633 .prompt = "%s(config-link-params)# ",
1634 };
1635
1636 #ifdef HAVE_BGPD
1637 static struct cmd_node rpki_node = {
1638 .name = "rpki",
1639 .node = RPKI_NODE,
1640 .parent_node = CONFIG_NODE,
1641 .prompt = "%s(config-rpki)# ",
1642 };
1643 #endif /* HAVE_BGPD */
1644
1645 #if HAVE_BFDD > 0
1646 static struct cmd_node bfd_node = {
1647 .name = "bfd",
1648 .node = BFD_NODE,
1649 .parent_node = CONFIG_NODE,
1650 .prompt = "%s(config-bfd)# ",
1651 };
1652
1653 static struct cmd_node bfd_peer_node = {
1654 .name = "bfd peer",
1655 .node = BFD_PEER_NODE,
1656 .parent_node = BFD_NODE,
1657 .prompt = "%s(config-bfd-peer)# ",
1658 };
1659
1660 static struct cmd_node bfd_profile_node = {
1661 .name = "bfd profile",
1662 .node = BFD_PROFILE_NODE,
1663 .parent_node = BFD_NODE,
1664 .prompt = "%s(config-bfd-profile)# ",
1665 };
1666 #endif /* HAVE_BFDD */
1667
1668 /* Defined in lib/vty.c */
1669 extern struct cmd_node vty_node;
1670
1671 /* When '^Z' is received from vty, move down to the enable mode. */
1672 static int vtysh_end(void)
1673 {
1674 switch (vty->node) {
1675 case VIEW_NODE:
1676 case ENABLE_NODE:
1677 /* Nothing to do. */
1678 break;
1679 default:
1680 vty->node = ENABLE_NODE;
1681 break;
1682 }
1683 return CMD_SUCCESS;
1684 }
1685
1686 DEFUNSH(VTYSH_REALLYALL, vtysh_end_all, vtysh_end_all_cmd, "end",
1687 "End current mode and change to enable mode\n")
1688 {
1689 return vtysh_end();
1690 }
1691
1692 DEFUNSH(VTYSH_SR, srv6, srv6_cmd,
1693 "srv6",
1694 "Segment-Routing SRv6 configration\n")
1695 {
1696 vty->node = SRV6_NODE;
1697 return CMD_SUCCESS;
1698 }
1699
1700 DEFUNSH(VTYSH_SR, srv6_locators, srv6_locators_cmd,
1701 "locators",
1702 "Segment-Routing SRv6 locators configration\n")
1703 {
1704 vty->node = SRV6_LOCS_NODE;
1705 return CMD_SUCCESS;
1706 }
1707
1708 DEFUNSH(VTYSH_SR, srv6_locator, srv6_locator_cmd,
1709 "locator WORD",
1710 "Segment Routing SRv6 locator\n"
1711 "Specify locator-name\n")
1712 {
1713 vty->node = SRV6_LOC_NODE;
1714 return CMD_SUCCESS;
1715 }
1716
1717 #ifdef HAVE_BGPD
1718 DEFUNSH(VTYSH_BGPD, router_bgp, router_bgp_cmd,
1719 "router bgp [(1-4294967295) [<view|vrf> WORD]]",
1720 ROUTER_STR BGP_STR AS_STR
1721 "BGP view\nBGP VRF\n"
1722 "View/VRF name\n")
1723 {
1724 vty->node = BGP_NODE;
1725 return CMD_SUCCESS;
1726 }
1727
1728 #ifdef KEEP_OLD_VPN_COMMANDS
1729 DEFUNSH(VTYSH_BGPD, address_family_vpnv4, address_family_vpnv4_cmd,
1730 "address-family vpnv4 [unicast]",
1731 "Enter Address Family command mode\n"
1732 "Address Family\n"
1733 "Address Family modifier\n")
1734 {
1735 vty->node = BGP_VPNV4_NODE;
1736 return CMD_SUCCESS;
1737 }
1738
1739 DEFUNSH(VTYSH_BGPD, address_family_vpnv6, address_family_vpnv6_cmd,
1740 "address-family vpnv6 [unicast]",
1741 "Enter Address Family command mode\n"
1742 "Address Family\n"
1743 "Address Family modifier\n")
1744 {
1745 vty->node = BGP_VPNV6_NODE;
1746 return CMD_SUCCESS;
1747 }
1748 #endif /* KEEP_OLD_VPN_COMMANDS */
1749
1750 DEFUNSH(VTYSH_BGPD, address_family_ipv4, address_family_ipv4_cmd,
1751 "address-family ipv4 [unicast]",
1752 "Enter Address Family command mode\n"
1753 "Address Family\n"
1754 "Address Family Modifier\n")
1755 {
1756 vty->node = BGP_IPV4_NODE;
1757 return CMD_SUCCESS;
1758 }
1759
1760 DEFUNSH(VTYSH_BGPD, address_family_flowspecv4, address_family_flowspecv4_cmd,
1761 "address-family ipv4 flowspec",
1762 "Enter Address Family command mode\n"
1763 "Address Family\n"
1764 "Address Family Modifier\n")
1765 {
1766 vty->node = BGP_FLOWSPECV4_NODE;
1767 return CMD_SUCCESS;
1768 }
1769
1770 DEFUNSH(VTYSH_BGPD, address_family_flowspecv6, address_family_flowspecv6_cmd,
1771 "address-family ipv6 flowspec",
1772 "Enter Address Family command mode\n"
1773 "Address Family\n"
1774 "Address Family Modifier\n")
1775 {
1776 vty->node = BGP_FLOWSPECV6_NODE;
1777 return CMD_SUCCESS;
1778 }
1779
1780 DEFUNSH(VTYSH_BGPD, address_family_ipv4_multicast,
1781 address_family_ipv4_multicast_cmd, "address-family ipv4 multicast",
1782 "Enter Address Family command mode\n"
1783 "Address Family\n"
1784 "Address Family modifier\n")
1785 {
1786 vty->node = BGP_IPV4M_NODE;
1787 return CMD_SUCCESS;
1788 }
1789
1790 DEFUNSH(VTYSH_BGPD, address_family_ipv4_vpn, address_family_ipv4_vpn_cmd,
1791 "address-family ipv4 vpn",
1792 "Enter Address Family command mode\n"
1793 "Address Family\n"
1794 "Address Family modifier\n")
1795 {
1796 vty->node = BGP_VPNV4_NODE;
1797 return CMD_SUCCESS;
1798 }
1799
1800 DEFUNSH(VTYSH_BGPD, address_family_ipv4_labeled_unicast,
1801 address_family_ipv4_labeled_unicast_cmd,
1802 "address-family ipv4 labeled-unicast",
1803 "Enter Address Family command mode\n"
1804 "Address Family\n"
1805 "Address Family modifier\n")
1806 {
1807 vty->node = BGP_IPV4L_NODE;
1808 return CMD_SUCCESS;
1809 }
1810
1811 DEFUNSH(VTYSH_BGPD, address_family_ipv6, address_family_ipv6_cmd,
1812 "address-family ipv6 [unicast]",
1813 "Enter Address Family command mode\n"
1814 "Address Family\n"
1815 "Address Family modifier\n")
1816 {
1817 vty->node = BGP_IPV6_NODE;
1818 return CMD_SUCCESS;
1819 }
1820
1821 DEFUNSH(VTYSH_BGPD, address_family_ipv6_multicast,
1822 address_family_ipv6_multicast_cmd, "address-family ipv6 multicast",
1823 "Enter Address Family command mode\n"
1824 "Address Family\n"
1825 "Address Family modifier\n")
1826 {
1827 vty->node = BGP_IPV6M_NODE;
1828 return CMD_SUCCESS;
1829 }
1830
1831 DEFUNSH(VTYSH_BGPD, address_family_ipv6_vpn, address_family_ipv6_vpn_cmd,
1832 "address-family ipv6 vpn",
1833 "Enter Address Family command mode\n"
1834 "Address Family\n"
1835 "Address Family modifier\n")
1836 {
1837 vty->node = BGP_VPNV6_NODE;
1838 return CMD_SUCCESS;
1839 }
1840
1841 DEFUNSH(VTYSH_BGPD, address_family_ipv6_labeled_unicast,
1842 address_family_ipv6_labeled_unicast_cmd,
1843 "address-family ipv6 labeled-unicast",
1844 "Enter Address Family command mode\n"
1845 "Address Family\n"
1846 "Address Family modifier\n")
1847 {
1848 vty->node = BGP_IPV6L_NODE;
1849 return CMD_SUCCESS;
1850 }
1851
1852 DEFUNSH(VTYSH_BGPD,
1853 rpki,
1854 rpki_cmd,
1855 "rpki",
1856 "Enable rpki and enter rpki configuration mode\n")
1857 {
1858 vty->node = RPKI_NODE;
1859 return CMD_SUCCESS;
1860 }
1861
1862 DEFUNSH(VTYSH_BGPD,
1863 bmp_targets,
1864 bmp_targets_cmd,
1865 "bmp targets BMPTARGETS",
1866 "BGP Monitoring Protocol\n"
1867 "Create BMP target group\n"
1868 "Name of the BMP target group\n")
1869 {
1870 vty->node = BMP_NODE;
1871 return CMD_SUCCESS;
1872 }
1873
1874 DEFUNSH(VTYSH_BGPD,
1875 bgp_srv6,
1876 bgp_srv6_cmd,
1877 "segment-routing srv6",
1878 "Segment-Routing configuration\n"
1879 "Segment-Routing SRv6 configuration\n")
1880 {
1881 vty->node = BGP_SRV6_NODE;
1882 return CMD_SUCCESS;
1883 }
1884
1885 DEFUNSH(VTYSH_BGPD,
1886 exit_bgp_srv6,
1887 exit_bgp_srv6_cmd,
1888 "exit",
1889 "exit Segment-Routing SRv6 configuration\n")
1890 {
1891 if (vty->node == BGP_SRV6_NODE)
1892 vty->node = BGP_NODE;
1893 return CMD_SUCCESS;
1894 }
1895
1896 DEFUNSH(VTYSH_BGPD,
1897 quit_bgp_srv6,
1898 quit_bgp_srv6_cmd,
1899 "quit",
1900 "quit Segment-Routing SRv6 configuration\n")
1901 {
1902 if (vty->node == BGP_SRV6_NODE)
1903 vty->node = BGP_NODE;
1904 return CMD_SUCCESS;
1905 }
1906
1907 DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
1908 "address-family <l2vpn evpn>",
1909 "Enter Address Family command mode\n"
1910 "Address Family\n"
1911 "Address Family modifier\n")
1912 {
1913 vty->node = BGP_EVPN_NODE;
1914 return CMD_SUCCESS;
1915 }
1916
1917 #if defined(HAVE_CUMULUS)
1918 #if CONFDATE > 20211115
1919 CPP_NOTICE("Use of `address-family evpn` is deprecated please remove don't forget frr-reload.py")
1920 #endif
1921 DEFUNSH_HIDDEN(VTYSH_BGPD, address_family_evpn2, address_family_evpn2_cmd,
1922 "address-family evpn",
1923 "Enter Address Family command mode\n"
1924 "EVPN Address family\n")
1925 {
1926 vty_out(vty,
1927 "This command is deprecated please convert to `address-family l2vpn evpn`\n");
1928 vty->node = BGP_EVPN_NODE;
1929 return CMD_SUCCESS;
1930 }
1931 #endif
1932
1933 DEFUNSH(VTYSH_BGPD, bgp_evpn_vni, bgp_evpn_vni_cmd, "vni " CMD_VNI_RANGE,
1934 "VXLAN Network Identifier\n"
1935 "VNI number\n")
1936 {
1937 vty->node = BGP_EVPN_VNI_NODE;
1938 return CMD_SUCCESS;
1939 }
1940
1941 #if defined(ENABLE_BGP_VNC)
1942 DEFUNSH(VTYSH_BGPD, vnc_defaults, vnc_defaults_cmd, "vnc defaults",
1943 "VNC/RFP related configuration\n"
1944 "Configure default NVE group\n")
1945 {
1946 vty->node = BGP_VNC_DEFAULTS_NODE;
1947 return CMD_SUCCESS;
1948 }
1949
1950 DEFUNSH(VTYSH_BGPD, vnc_nve_group, vnc_nve_group_cmd, "vnc nve-group NAME",
1951 "VNC/RFP related configuration\n"
1952 "Configure a NVE group\n"
1953 "Group name\n")
1954 {
1955 vty->node = BGP_VNC_NVE_GROUP_NODE;
1956 return CMD_SUCCESS;
1957 }
1958
1959 DEFUNSH(VTYSH_BGPD, vnc_vrf_policy, vnc_vrf_policy_cmd, "vrf-policy NAME",
1960 "Configure a VRF policy group\n"
1961 "Group name\n")
1962 {
1963 vty->node = BGP_VRF_POLICY_NODE;
1964 return CMD_SUCCESS;
1965 }
1966
1967 DEFUNSH(VTYSH_BGPD, vnc_l2_group, vnc_l2_group_cmd, "vnc l2-group NAME",
1968 "VNC/RFP related configuration\n"
1969 "Configure a L2 group\n"
1970 "Group name\n")
1971 {
1972 vty->node = BGP_VNC_L2_GROUP_NODE;
1973 return CMD_SUCCESS;
1974 }
1975
1976 DEFUNSH(VTYSH_BGPD, exit_vnc_config, exit_vnc_config_cmd, "exit-vnc",
1977 "Exit from VNC configuration mode\n")
1978 {
1979 if (vty->node == BGP_VNC_DEFAULTS_NODE
1980 || vty->node == BGP_VNC_NVE_GROUP_NODE
1981 || vty->node == BGP_VNC_L2_GROUP_NODE)
1982 vty->node = BGP_NODE;
1983 return CMD_SUCCESS;
1984 }
1985
1986 DEFUNSH(VTYSH_BGPD, exit_vrf_policy, exit_vrf_policy_cmd, "exit-vrf-policy",
1987 "Exit from VRF policy configuration mode\n")
1988 {
1989 if (vty->node == BGP_VRF_POLICY_NODE)
1990 vty->node = BGP_NODE;
1991 return CMD_SUCCESS;
1992 }
1993 #endif
1994 #endif /* HAVE_BGPD */
1995
1996 DEFUNSH(VTYSH_KEYS, key_chain, key_chain_cmd, "key chain WORD",
1997 "Authentication key management\n"
1998 "Key-chain management\n"
1999 "Key-chain name\n")
2000 {
2001 vty->node = KEYCHAIN_NODE;
2002 return CMD_SUCCESS;
2003 }
2004
2005 DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)",
2006 "Configure a key\n"
2007 "Key identifier number\n")
2008 {
2009 vty->node = KEYCHAIN_KEY_NODE;
2010 return CMD_SUCCESS;
2011 }
2012
2013 #ifdef HAVE_RIPD
2014 DEFUNSH(VTYSH_RIPD, router_rip, router_rip_cmd, "router rip [vrf NAME]",
2015 ROUTER_STR "RIP\n" VRF_CMD_HELP_STR)
2016 {
2017 vty->node = RIP_NODE;
2018 return CMD_SUCCESS;
2019 }
2020 #endif /* HAVE_RIPD */
2021
2022 #ifdef HAVE_RIPNGD
2023 DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng [vrf NAME]",
2024 ROUTER_STR "RIPng\n" VRF_CMD_HELP_STR)
2025 {
2026 vty->node = RIPNG_NODE;
2027 return CMD_SUCCESS;
2028 }
2029 #endif /* HAVE_RIPNGD */
2030
2031 #ifdef HAVE_OSPFD
2032 DEFUNSH(VTYSH_OSPFD, router_ospf, router_ospf_cmd,
2033 "router ospf [(1-65535)] [vrf NAME]",
2034 "Enable a routing process\n"
2035 "Start OSPF configuration\n"
2036 "Instance ID\n"
2037 VRF_CMD_HELP_STR)
2038 {
2039 vty->node = OSPF_NODE;
2040 return CMD_SUCCESS;
2041 }
2042 #endif /* HAVE_OSPFD */
2043
2044 #ifdef HAVE_EIGRPD
2045 DEFUNSH(VTYSH_EIGRPD, router_eigrp, router_eigrp_cmd, "router eigrp (1-65535) [vrf NAME]",
2046 "Enable a routing process\n"
2047 "Start EIGRP configuration\n"
2048 "AS number to use\n"
2049 VRF_CMD_HELP_STR)
2050 {
2051 vty->node = EIGRP_NODE;
2052 return CMD_SUCCESS;
2053 }
2054 #endif /* HAVE_EIGRPD */
2055
2056 #ifdef HAVE_BABELD
2057 DEFUNSH(VTYSH_BABELD, router_babel, router_babel_cmd, "router babel",
2058 "Enable a routing process\n"
2059 "Make Babel instance command\n")
2060 {
2061 vty->node = BABEL_NODE;
2062 return CMD_SUCCESS;
2063 }
2064 #endif /* HAVE_BABELD */
2065
2066 #ifdef HAVE_OSPF6D
2067 DEFUNSH(VTYSH_OSPF6D, router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
2068 ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
2069 {
2070 vty->node = OSPF6_NODE;
2071 return CMD_SUCCESS;
2072 }
2073 #endif
2074
2075 #if defined(HAVE_LDPD)
2076 DEFUNSH(VTYSH_LDPD, ldp_mpls_ldp, ldp_mpls_ldp_cmd, "mpls ldp",
2077 "Global MPLS configuration subcommands\n"
2078 "Label Distribution Protocol\n")
2079 {
2080 vty->node = LDP_NODE;
2081 return CMD_SUCCESS;
2082 }
2083
2084 DEFUNSH(VTYSH_LDPD, ldp_address_family_ipv4, ldp_address_family_ipv4_cmd,
2085 "address-family ipv4",
2086 "Configure Address Family and its parameters\n"
2087 "IPv4\n")
2088 {
2089 vty->node = LDP_IPV4_NODE;
2090 return CMD_SUCCESS;
2091 }
2092
2093 DEFUNSH(VTYSH_LDPD, ldp_address_family_ipv6, ldp_address_family_ipv6_cmd,
2094 "address-family ipv6",
2095 "Configure Address Family and its parameters\n"
2096 "IPv6\n")
2097 {
2098 vty->node = LDP_IPV6_NODE;
2099 return CMD_SUCCESS;
2100 }
2101
2102 DEFUNSH(VTYSH_LDPD, ldp_exit_address_family, ldp_exit_address_family_cmd,
2103 "exit-address-family", "Exit from Address Family configuration mode\n")
2104 {
2105 if (vty->node == LDP_IPV4_NODE || vty->node == LDP_IPV6_NODE)
2106 vty->node = LDP_NODE;
2107 return CMD_SUCCESS;
2108 }
2109
2110 DEFUNSH(VTYSH_LDPD, ldp_interface_ifname, ldp_interface_ifname_cmd,
2111 "interface IFNAME",
2112 "Enable LDP on an interface and enter interface submode\n"
2113 "Interface's name\n")
2114 {
2115 switch (vty->node) {
2116 case LDP_IPV4_NODE:
2117 vty->node = LDP_IPV4_IFACE_NODE;
2118 break;
2119 case LDP_IPV6_NODE:
2120 vty->node = LDP_IPV6_IFACE_NODE;
2121 break;
2122 default:
2123 break;
2124 }
2125
2126 return CMD_SUCCESS;
2127 }
2128
2129 DEFUNSH(VTYSH_LDPD, ldp_l2vpn_word_type_vpls, ldp_l2vpn_word_type_vpls_cmd,
2130 "l2vpn WORD type vpls",
2131 "Configure l2vpn commands\n"
2132 "L2VPN name\n"
2133 "L2VPN type\n"
2134 "Virtual Private LAN Service\n")
2135 {
2136 vty->node = LDP_L2VPN_NODE;
2137 return CMD_SUCCESS;
2138 }
2139
2140 DEFUNSH(VTYSH_LDPD, ldp_member_pseudowire_ifname,
2141 ldp_member_pseudowire_ifname_cmd, "member pseudowire IFNAME",
2142 "L2VPN member configuration\n"
2143 "Pseudowire interface\n"
2144 "Interface's name\n")
2145 {
2146 vty->node = LDP_PSEUDOWIRE_NODE;
2147 return CMD_SUCCESS;
2148 }
2149 #endif
2150
2151 #ifdef HAVE_ISISD
2152 DEFUNSH(VTYSH_ISISD, router_isis, router_isis_cmd,
2153 "router isis WORD [vrf NAME]",
2154 ROUTER_STR
2155 "ISO IS-IS\n"
2156 "ISO Routing area tag\n" VRF_CMD_HELP_STR)
2157 {
2158 vty->node = ISIS_NODE;
2159 return CMD_SUCCESS;
2160 }
2161 #endif /* HAVE_ISISD */
2162
2163 #ifdef HAVE_FABRICD
2164 DEFUNSH(VTYSH_FABRICD, router_openfabric, router_openfabric_cmd, "router openfabric WORD",
2165 ROUTER_STR
2166 "OpenFabric routing protocol\n"
2167 "ISO Routing area tag\n")
2168 {
2169 vty->node = OPENFABRIC_NODE;
2170 return CMD_SUCCESS;
2171 }
2172 #endif /* HAVE_FABRICD */
2173
2174 DEFUNSH(VTYSH_SR, segment_routing, segment_routing_cmd,
2175 "segment-routing",
2176 "Configure segment routing\n")
2177 {
2178 vty->node = SEGMENT_ROUTING_NODE;
2179 return CMD_SUCCESS;
2180 }
2181
2182 #if defined (HAVE_PATHD)
2183 DEFUNSH(VTYSH_PATHD, sr_traffic_eng, sr_traffic_eng_cmd,
2184 "traffic-eng",
2185 "Configure SR traffic engineering\n")
2186 {
2187 vty->node = SR_TRAFFIC_ENG_NODE;
2188 return CMD_SUCCESS;
2189 }
2190
2191 DEFUNSH(VTYSH_PATHD, srte_segment_list, srte_segment_list_cmd,
2192 "segment-list WORD$name",
2193 "Segment List\n"
2194 "Segment List Name\n")
2195 {
2196 vty->node = SR_SEGMENT_LIST_NODE;
2197 return CMD_SUCCESS;
2198 }
2199
2200 DEFUNSH(VTYSH_PATHD, srte_policy, srte_policy_cmd,
2201 "policy color (0-4294967295) endpoint <A.B.C.D|X:X::X:X>",
2202 "Segment Routing Policy\n"
2203 "SR Policy color\n"
2204 "SR Policy color value\n"
2205 "SR Policy endpoint\n"
2206 "SR Policy endpoint IPv4 address\n"
2207 "SR Policy endpoint IPv6 address\n")
2208 {
2209 vty->node = SR_POLICY_NODE;
2210 return CMD_SUCCESS;
2211 }
2212
2213 DEFUNSH(VTYSH_PATHD, srte_policy_candidate_dyn_path,
2214 srte_policy_candidate_dyn_path_cmd,
2215 "candidate-path preference (0-4294967295) name WORD dynamic",
2216 "Segment Routing Policy Candidate Path\n"
2217 "Segment Routing Policy Candidate Path Preference\n"
2218 "Administrative Preference\n"
2219 "Segment Routing Policy Candidate Path Name\n"
2220 "Symbolic Name\n"
2221 "Dynamic Path\n")
2222 {
2223 vty->node = SR_CANDIDATE_DYN_NODE;
2224 return CMD_SUCCESS;
2225 }
2226
2227 #if defined(HAVE_PATHD_PCEP)
2228
2229 DEFUNSH(VTYSH_PATHD, pcep, pcep_cmd,
2230 "pcep",
2231 "Configure SR pcep\n")
2232 {
2233 vty->node = PCEP_NODE;
2234 return CMD_SUCCESS;
2235 }
2236
2237 DEFUNSH(VTYSH_PATHD, pcep_cli_pcc, pcep_cli_pcc_cmd,
2238 "[no] pcc",
2239 NO_STR
2240 "PCC configuration\n")
2241 {
2242 vty->node = PCEP_PCC_NODE;
2243 return CMD_SUCCESS;
2244 }
2245
2246 DEFUNSH(VTYSH_PATHD, pcep_cli_pce, pcep_cli_pce_cmd,
2247 "[no] pce WORD",
2248 NO_STR
2249 "PCE configuration\n"
2250 "Peer name\n")
2251 {
2252 vty->node = PCEP_PCE_NODE;
2253 return CMD_SUCCESS;
2254 }
2255
2256 DEFUNSH(VTYSH_PATHD, pcep_cli_pcep_pce_config, pcep_cli_pcep_pce_config_cmd,
2257 "[no] pce-config WORD",
2258 NO_STR
2259 "PCEP peer Configuration Group\n"
2260 "PCEP peer Configuration Group name\n")
2261 {
2262 vty->node = PCEP_PCE_CONFIG_NODE;
2263 return CMD_SUCCESS;
2264 }
2265
2266 #endif /* HAVE_PATHD_PCEP */
2267
2268 #endif /* HAVE_PATHD */
2269
2270 DEFUNSH(VTYSH_RMAP, vtysh_route_map, vtysh_route_map_cmd,
2271 "route-map WORD <deny|permit> (1-65535)",
2272 "Create route-map or enter route-map command mode\n"
2273 "Route map tag\n"
2274 "Route map denies set operations\n"
2275 "Route map permits set operations\n"
2276 "Sequence to insert to/delete from existing route-map entry\n")
2277 {
2278 vty->node = RMAP_NODE;
2279 return CMD_SUCCESS;
2280 }
2281
2282 #ifdef HAVE_PBRD
2283 DEFUNSH(VTYSH_PBRD, vtysh_pbr_map, vtysh_pbr_map_cmd,
2284 "pbr-map PBRMAP seq (1-700)",
2285 "Create pbr-map or enter pbr-map command mode\n"
2286 "The name of the PBR MAP\n"
2287 "Sequence to insert to/delete from existing pbr-map entry\n"
2288 "Sequence number\n")
2289 {
2290 vty->node = PBRMAP_NODE;
2291 return CMD_SUCCESS;
2292 }
2293
2294 DEFSH(VTYSH_PBRD, vtysh_no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]",
2295 NO_STR
2296 "Delete pbr-map\n"
2297 "The name of the PBR MAP\n"
2298 "Sequence to delete from existing pbr-map entry\n"
2299 "Sequence number\n")
2300 #endif /* HAVE_PBRD */
2301
2302 #if HAVE_BFDD > 0
2303 DEFUNSH(VTYSH_BFDD, bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n")
2304 {
2305 vty->node = BFD_NODE;
2306 return CMD_SUCCESS;
2307 }
2308
2309 DEFUNSH(VTYSH_BFDD, bfd_peer_enter, bfd_peer_enter_cmd,
2310 "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
2311 "Configure peer\n"
2312 "IPv4 peer address\n"
2313 "IPv6 peer address\n"
2314 "Configure multihop\n"
2315 "Configure local address\n"
2316 "IPv4 local address\n"
2317 "IPv6 local address\n"
2318 INTERFACE_STR
2319 "Configure interface name to use\n"
2320 "Configure VRF\n"
2321 "Configure VRF name\n")
2322 {
2323 vty->node = BFD_PEER_NODE;
2324 return CMD_SUCCESS;
2325 }
2326
2327 DEFUNSH(VTYSH_BFDD, bfd_profile_enter, bfd_profile_enter_cmd,
2328 "profile BFDPROF",
2329 BFD_PROFILE_STR
2330 BFD_PROFILE_NAME_STR)
2331 {
2332 vty->node = BFD_PROFILE_NODE;
2333 return CMD_SUCCESS;
2334 }
2335 #endif /* HAVE_BFDD */
2336
2337 DEFUNSH(VTYSH_ALL, vtysh_line_vty, vtysh_line_vty_cmd, "line vty",
2338 "Configure a terminal line\n"
2339 "Virtual terminal\n")
2340 {
2341 vty->node = VTY_NODE;
2342 return CMD_SUCCESS;
2343 }
2344
2345 DEFUNSH(VTYSH_REALLYALL, vtysh_enable, vtysh_enable_cmd, "enable",
2346 "Turn on privileged mode command\n")
2347 {
2348 vty->node = ENABLE_NODE;
2349 return CMD_SUCCESS;
2350 }
2351
2352 DEFUNSH(VTYSH_REALLYALL, vtysh_disable, vtysh_disable_cmd, "disable",
2353 "Turn off privileged mode command\n")
2354 {
2355 if (vty->node == ENABLE_NODE)
2356 vty->node = VIEW_NODE;
2357 return CMD_SUCCESS;
2358 }
2359
2360 DEFUNSH(VTYSH_REALLYALL, vtysh_config_terminal, vtysh_config_terminal_cmd,
2361 "configure [terminal]",
2362 "Configuration from vty interface\n"
2363 "Configuration terminal\n")
2364 {
2365 vty->node = CONFIG_NODE;
2366 return CMD_SUCCESS;
2367 }
2368
2369 static int vtysh_exit(struct vty *vty)
2370 {
2371 struct cmd_node *cnode = vector_lookup(cmdvec, vty->node);
2372
2373 if (vty->node == VIEW_NODE || vty->node == ENABLE_NODE)
2374 exit(0);
2375 if (cnode->node_exit)
2376 cnode->node_exit(vty);
2377 if (cnode->parent_node)
2378 vty->node = cnode->parent_node;
2379
2380 if (vty->node == CONFIG_NODE) {
2381 /* resync in case one of the daemons is somewhere else */
2382 vtysh_execute("end");
2383 vtysh_execute("configure");
2384 }
2385 return CMD_SUCCESS;
2386 }
2387
2388 DEFUNSH(VTYSH_REALLYALL, vtysh_exit_all, vtysh_exit_all_cmd, "exit",
2389 "Exit current mode and down to previous mode\n")
2390 {
2391 return vtysh_exit(vty);
2392 }
2393
2394 DEFUNSH(VTYSH_REALLYALL, vtysh_quit_all, vtysh_quit_all_cmd, "quit",
2395 "Exit current mode and down to previous mode\n")
2396 {
2397 return vtysh_exit_all(self, vty, argc, argv);
2398 }
2399
2400 #ifdef HAVE_BGPD
2401 DEFUNSH(VTYSH_BGPD, exit_address_family, exit_address_family_cmd,
2402 "exit-address-family", "Exit from Address Family configuration mode\n")
2403 {
2404 if (vty->node == BGP_IPV4_NODE || vty->node == BGP_IPV4M_NODE
2405 || vty->node == BGP_IPV4L_NODE || vty->node == BGP_VPNV4_NODE
2406 || vty->node == BGP_VPNV6_NODE || vty->node == BGP_IPV6_NODE
2407 || vty->node == BGP_IPV6L_NODE || vty->node == BGP_IPV6M_NODE
2408 || vty->node == BGP_EVPN_NODE
2409 || vty->node == BGP_FLOWSPECV4_NODE
2410 || vty->node == BGP_FLOWSPECV6_NODE)
2411 vty->node = BGP_NODE;
2412 return CMD_SUCCESS;
2413 }
2414
2415 DEFUNSH(VTYSH_BGPD, exit_vni, exit_vni_cmd, "exit-vni", "Exit from VNI mode\n")
2416 {
2417 if (vty->node == BGP_EVPN_VNI_NODE)
2418 vty->node = BGP_EVPN_NODE;
2419 return CMD_SUCCESS;
2420 }
2421
2422 DEFUNSH(VTYSH_BGPD, rpki_exit, rpki_exit_cmd, "exit",
2423 "Exit current mode and down to previous mode\n")
2424 {
2425 vtysh_exit(vty);
2426 return CMD_SUCCESS;
2427 }
2428
2429 DEFUNSH(VTYSH_BGPD, rpki_quit, rpki_quit_cmd, "quit",
2430 "Exit current mode and down to previous mode\n")
2431 {
2432 return rpki_exit(self, vty, argc, argv);
2433 }
2434
2435 DEFUNSH(VTYSH_BGPD, bmp_exit, bmp_exit_cmd, "exit",
2436 "Exit current mode and down to previous mode\n")
2437 {
2438 vtysh_exit(vty);
2439 return CMD_SUCCESS;
2440 }
2441
2442 DEFUNSH(VTYSH_BGPD, bmp_quit, bmp_quit_cmd, "quit",
2443 "Exit current mode and down to previous mode\n")
2444 {
2445 return bmp_exit(self, vty, argc, argv);
2446 }
2447 #endif /* HAVE_BGPD */
2448
2449 DEFUNSH(VTYSH_VRF, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf",
2450 "Exit from VRF configuration mode\n")
2451 {
2452 if (vty->node == VRF_NODE)
2453 vty->node = CONFIG_NODE;
2454 return CMD_SUCCESS;
2455 }
2456
2457 DEFUNSH(VTYSH_SR, exit_srv6_config, exit_srv6_config_cmd, "exit",
2458 "Exit from SRv6 configuration mode\n")
2459 {
2460 if (vty->node == SRV6_NODE)
2461 vty->node = SEGMENT_ROUTING_NODE;
2462 return CMD_SUCCESS;
2463 }
2464
2465 DEFUNSH(VTYSH_SR, exit_srv6_locs_config, exit_srv6_locs_config_cmd, "exit",
2466 "Exit from SRv6-locator configuration mode\n")
2467 {
2468 if (vty->node == SRV6_LOCS_NODE)
2469 vty->node = SRV6_NODE;
2470 return CMD_SUCCESS;
2471 }
2472
2473 DEFUNSH(VTYSH_SR, exit_srv6_loc_config, exit_srv6_loc_config_cmd, "exit",
2474 "Exit from SRv6-locators configuration mode\n")
2475 {
2476 if (vty->node == SRV6_LOC_NODE)
2477 vty->node = SRV6_LOCS_NODE;
2478 return CMD_SUCCESS;
2479 }
2480
2481 #ifdef HAVE_RIPD
2482 DEFUNSH(VTYSH_RIPD, vtysh_exit_ripd, vtysh_exit_ripd_cmd, "exit",
2483 "Exit current mode and down to previous mode\n")
2484 {
2485 return vtysh_exit(vty);
2486 }
2487
2488 DEFUNSH(VTYSH_RIPD, vtysh_quit_ripd, vtysh_quit_ripd_cmd, "quit",
2489 "Exit current mode and down to previous mode\n")
2490 {
2491 return vtysh_exit_ripd(self, vty, argc, argv);
2492 }
2493 #endif /* HAVE_RIPD */
2494
2495 #ifdef HAVE_RIPNGD
2496 DEFUNSH(VTYSH_RIPNGD, vtysh_exit_ripngd, vtysh_exit_ripngd_cmd, "exit",
2497 "Exit current mode and down to previous mode\n")
2498 {
2499 return vtysh_exit(vty);
2500 }
2501
2502 DEFUNSH(VTYSH_RIPNGD, vtysh_quit_ripngd, vtysh_quit_ripngd_cmd, "quit",
2503 "Exit current mode and down to previous mode\n")
2504 {
2505 return vtysh_exit_ripngd(self, vty, argc, argv);
2506 }
2507 #endif /* HAVE_RIPNGD */
2508
2509 DEFUNSH(VTYSH_RMAP, vtysh_exit_rmap, vtysh_exit_rmap_cmd, "exit",
2510 "Exit current mode and down to previous mode\n")
2511 {
2512 return vtysh_exit(vty);
2513 }
2514
2515 DEFUNSH(VTYSH_RMAP, vtysh_quit_rmap, vtysh_quit_rmap_cmd, "quit",
2516 "Exit current mode and down to previous mode\n")
2517 {
2518 return vtysh_exit_rmap(self, vty, argc, argv);
2519 }
2520
2521 #ifdef HAVE_PBRD
2522 DEFUNSH(VTYSH_PBRD, vtysh_exit_pbr_map, vtysh_exit_pbr_map_cmd, "exit",
2523 "Exit current mode and down to previous mode\n")
2524 {
2525 return vtysh_exit(vty);
2526 }
2527
2528 DEFUNSH(VTYSH_PBRD, vtysh_quit_pbr_map, vtysh_quit_pbr_map_cmd, "quit",
2529 "Exit current mode and down to previous mode\n")
2530 {
2531 return vtysh_exit_rmap(self, vty, argc, argv);
2532 }
2533 #endif /* HAVE_PBRD */
2534
2535 #ifdef HAVE_BGPD
2536 DEFUNSH(VTYSH_BGPD, vtysh_exit_bgpd, vtysh_exit_bgpd_cmd, "exit",
2537 "Exit current mode and down to previous mode\n")
2538 {
2539 return vtysh_exit(vty);
2540 }
2541
2542 DEFUNSH(VTYSH_BGPD, vtysh_quit_bgpd, vtysh_quit_bgpd_cmd, "quit",
2543 "Exit current mode and down to previous mode\n")
2544 {
2545 return vtysh_exit_bgpd(self, vty, argc, argv);
2546 }
2547 #endif /* HAVE_BGPD */
2548
2549 #ifdef HAVE_OSPFD
2550 DEFUNSH(VTYSH_OSPFD, vtysh_exit_ospfd, vtysh_exit_ospfd_cmd, "exit",
2551 "Exit current mode and down to previous mode\n")
2552 {
2553 return vtysh_exit(vty);
2554 }
2555
2556 DEFUNSH(VTYSH_OSPFD, vtysh_quit_ospfd, vtysh_quit_ospfd_cmd, "quit",
2557 "Exit current mode and down to previous mode\n")
2558 {
2559 return vtysh_exit_ospfd(self, vty, argc, argv);
2560 }
2561 #endif /* HAVE_OSPFD */
2562
2563 #ifdef HAVE_EIGRPD
2564 DEFUNSH(VTYSH_EIGRPD, vtysh_exit_eigrpd, vtysh_exit_eigrpd_cmd, "exit",
2565 "Exit current mode and down to previous mode\n")
2566 {
2567 return vtysh_exit(vty);
2568 }
2569
2570 DEFUNSH(VTYSH_EIGRPD, vtysh_quit_eigrpd, vtysh_quit_eigrpd_cmd, "quit",
2571 "Exit current mode and down to previous mode\n")
2572 {
2573 return vtysh_exit(vty);
2574 }
2575 #endif /* HAVE_EIGRPD */
2576
2577 #ifdef HAVE_BABELD
2578 DEFUNSH(VTYSH_BABELD, vtysh_exit_babeld, vtysh_exit_babeld_cmd, "exit",
2579 "Exit current mode and down to previous mode\n")
2580 {
2581 return vtysh_exit(vty);
2582 }
2583
2584 DEFUNSH(VTYSH_BABELD, vtysh_quit_babeld, vtysh_quit_babeld_cmd, "quit",
2585 "Exit current mode and down to previous mode\n")
2586 {
2587 return vtysh_exit(vty);
2588 }
2589 #endif /* HAVE_BABELD */
2590
2591 #ifdef HAVE_OSPF6D
2592 DEFUNSH(VTYSH_OSPF6D, vtysh_exit_ospf6d, vtysh_exit_ospf6d_cmd, "exit",
2593 "Exit current mode and down to previous mode\n")
2594 {
2595 return vtysh_exit(vty);
2596 }
2597
2598 DEFUNSH(VTYSH_OSPF6D, vtysh_quit_ospf6d, vtysh_quit_ospf6d_cmd, "quit",
2599 "Exit current mode and down to previous mode\n")
2600 {
2601 return vtysh_exit_ospf6d(self, vty, argc, argv);
2602 }
2603 #endif /* HAVE_OSPF6D */
2604
2605 #if defined(HAVE_LDPD)
2606 DEFUNSH(VTYSH_LDPD, vtysh_exit_ldpd, vtysh_exit_ldpd_cmd, "exit",
2607 "Exit current mode and down to previous mode\n")
2608 {
2609 return vtysh_exit(vty);
2610 }
2611
2612 ALIAS(vtysh_exit_ldpd, vtysh_quit_ldpd_cmd, "quit",
2613 "Exit current mode and down to previous mode\n")
2614 #endif
2615
2616 #ifdef HAVE_ISISD
2617 DEFUNSH(VTYSH_ISISD, vtysh_exit_isisd, vtysh_exit_isisd_cmd, "exit",
2618 "Exit current mode and down to previous mode\n")
2619 {
2620 return vtysh_exit(vty);
2621 }
2622
2623 DEFUNSH(VTYSH_ISISD, vtysh_quit_isisd, vtysh_quit_isisd_cmd, "quit",
2624 "Exit current mode and down to previous mode\n")
2625 {
2626 return vtysh_exit_isisd(self, vty, argc, argv);
2627 }
2628 #endif /* HAVE_ISISD */
2629
2630 #if HAVE_BFDD > 0
2631 DEFUNSH(VTYSH_BFDD, vtysh_exit_bfdd, vtysh_exit_bfdd_cmd, "exit",
2632 "Exit current mode and down to previous mode\n")
2633 {
2634 return vtysh_exit(vty);
2635 }
2636
2637 ALIAS(vtysh_exit_bfdd, vtysh_quit_bfdd_cmd, "quit",
2638 "Exit current mode and down to previous mode\n")
2639 #endif
2640
2641 #ifdef HAVE_FABRICD
2642 DEFUNSH(VTYSH_FABRICD, vtysh_exit_fabricd, vtysh_exit_fabricd_cmd, "exit",
2643 "Exit current mode and down to previous mode\n")
2644 {
2645 return vtysh_exit(vty);
2646 }
2647
2648 DEFUNSH(VTYSH_FABRICD, vtysh_quit_fabricd, vtysh_quit_fabricd_cmd, "quit",
2649 "Exit current mode and down to previous mode\n")
2650 {
2651 return vtysh_exit_fabricd(self, vty, argc, argv);
2652 }
2653 #endif /* HAVE_FABRICD */
2654
2655 DEFUNSH(VTYSH_KEYS, vtysh_exit_keys, vtysh_exit_keys_cmd, "exit",
2656 "Exit current mode and down to previous mode\n")
2657 {
2658 return vtysh_exit(vty);
2659 }
2660
2661 DEFUNSH(VTYSH_KEYS, vtysh_quit_keys, vtysh_quit_keys_cmd, "quit",
2662 "Exit current mode and down to previous mode\n")
2663 {
2664 return vtysh_exit_keys(self, vty, argc, argv);
2665 }
2666
2667 DEFUNSH(VTYSH_SR, vtysh_exit_sr, vtysh_exit_sr_cmd, "exit",
2668 "Exit current mode and down to previous mode\n")
2669 {
2670 return vtysh_exit(vty);
2671 }
2672
2673 DEFUNSH(VTYSH_SR, vtysh_quit_sr, vtysh_quit_sr_cmd, "quit",
2674 "Exit current mode and down to previous mode\n")
2675 {
2676 return vtysh_exit(vty);
2677 }
2678
2679 #if defined(HAVE_PATHD)
2680 DEFUNSH(VTYSH_PATHD, vtysh_exit_pathd, vtysh_exit_pathd_cmd, "exit",
2681 "Exit current mode and down to previous mode\n")
2682 {
2683 return vtysh_exit(vty);
2684 }
2685
2686 DEFUNSH(VTYSH_PATHD, vtysh_quit_pathd, vtysh_quit_pathd_cmd, "quit",
2687 "Exit current mode and down to previous mode\n")
2688 {
2689 return vtysh_exit_pathd(self, vty, argc, argv);
2690 }
2691 #endif /* HAVE_PATHD */
2692
2693 DEFUNSH(VTYSH_ALL, vtysh_exit_line_vty, vtysh_exit_line_vty_cmd, "exit",
2694 "Exit current mode and down to previous mode\n")
2695 {
2696 return vtysh_exit(vty);
2697 }
2698
2699 DEFUNSH(VTYSH_ALL, vtysh_quit_line_vty, vtysh_quit_line_vty_cmd, "quit",
2700 "Exit current mode and down to previous mode\n")
2701 {
2702 return vtysh_exit_line_vty(self, vty, argc, argv);
2703 }
2704
2705 DEFUNSH(VTYSH_INTERFACE, vtysh_interface, vtysh_interface_cmd,
2706 "interface IFNAME [vrf NAME]",
2707 "Select an interface to configure\n"
2708 "Interface's name\n" VRF_CMD_HELP_STR)
2709 {
2710 vty->node = INTERFACE_NODE;
2711 return CMD_SUCCESS;
2712 }
2713
2714 DEFUNSH(VTYSH_ZEBRA, vtysh_pseudowire, vtysh_pseudowire_cmd,
2715 "pseudowire IFNAME",
2716 "Static pseudowire configuration\n"
2717 "Pseudowire name\n")
2718 {
2719 vty->node = PW_NODE;
2720 return CMD_SUCCESS;
2721 }
2722
2723 DEFUNSH(VTYSH_NH_GROUP,
2724 vtysh_nexthop_group, vtysh_nexthop_group_cmd,
2725 "nexthop-group NHGNAME",
2726 "Nexthop Group configuration\n"
2727 "Name of the Nexthop Group\n")
2728 {
2729 vty->node = NH_GROUP_NODE;
2730 return CMD_SUCCESS;
2731 }
2732
2733 DEFSH(VTYSH_NH_GROUP, vtysh_no_nexthop_group_cmd,
2734 "no nexthop-group NHGNAME",
2735 NO_STR
2736 "Nexthop Group Configuration\n"
2737 "Name of the Nexthop Group\n")
2738
2739 DEFUNSH(VTYSH_VRF, vtysh_vrf, vtysh_vrf_cmd, "vrf NAME",
2740 "Select a VRF to configure\n"
2741 "VRF's name\n")
2742 {
2743 vty->node = VRF_NODE;
2744 return CMD_SUCCESS;
2745 }
2746
2747 DEFSH(VTYSH_ZEBRA, vtysh_vrf_netns_cmd,
2748 "netns NAME",
2749 "Attach VRF to a Namespace\n"
2750 "The file name in " NS_RUN_DIR ", or a full pathname\n")
2751
2752 DEFSH(VTYSH_ZEBRA, vtysh_no_vrf_netns_cmd,
2753 "no netns [NAME]",
2754 NO_STR
2755 "Detach VRF from a Namespace\n"
2756 "The file name in " NS_RUN_DIR ", or a full pathname\n")
2757
2758 DEFUNSH(VTYSH_VRF, vtysh_exit_vrf, vtysh_exit_vrf_cmd, "exit",
2759 "Exit current mode and down to previous mode\n")
2760 {
2761 return vtysh_exit(vty);
2762 }
2763
2764 DEFUNSH(VTYSH_VRF, vtysh_quit_vrf, vtysh_quit_vrf_cmd, "quit",
2765 "Exit current mode and down to previous mode\n")
2766 {
2767 return vtysh_exit_vrf(self, vty, argc, argv);
2768 }
2769
2770 DEFUNSH(VTYSH_NH_GROUP,
2771 vtysh_exit_nexthop_group, vtysh_exit_nexthop_group_cmd,
2772 "exit", "Exit current mode and down to previous mode\n")
2773 {
2774 return vtysh_exit(vty);
2775 }
2776
2777 DEFUNSH(VTYSH_NH_GROUP,
2778 vtysh_quit_nexthop_group, vtysh_quit_nexthop_group_cmd,
2779 "quit", "Exit current mode and down to previous mode\n")
2780 {
2781 return vtysh_exit_nexthop_group(self, vty, argc, argv);
2782 }
2783
2784 DEFUNSH(VTYSH_INTERFACE, vtysh_exit_interface, vtysh_exit_interface_cmd, "exit",
2785 "Exit current mode and down to previous mode\n")
2786 {
2787 return vtysh_exit(vty);
2788 }
2789
2790 DEFUNSH(VTYSH_INTERFACE, vtysh_quit_interface, vtysh_quit_interface_cmd, "quit",
2791 "Exit current mode and down to previous mode\n")
2792 {
2793 return vtysh_exit_interface(self, vty, argc, argv);
2794 }
2795
2796 static char *do_prepend(struct vty *vty, struct cmd_token **argv, int argc)
2797 {
2798 const char *argstr[argc + 1];
2799 int i, off = 0;
2800
2801 if (vty->node != VIEW_NODE) {
2802 off = 1;
2803 argstr[0] = "do";
2804 }
2805
2806 for (i = 0; i < argc; i++)
2807 argstr[i + off] = argv[i]->arg;
2808
2809 return frrstr_join(argstr, argc + off, " ");
2810 }
2811
2812 static int show_per_daemon(struct vty *vty, struct cmd_token **argv, int argc,
2813 const char *headline)
2814 {
2815 unsigned int i;
2816 int ret = CMD_SUCCESS;
2817 char *line = do_prepend(vty, argv, argc);
2818
2819 for (i = 0; i < array_size(vtysh_client); i++)
2820 if (vtysh_client[i].fd >= 0 || vtysh_client[i].next) {
2821 vty_out(vty, headline, vtysh_client[i].name);
2822 ret = vtysh_client_execute(&vtysh_client[i], line);
2823 vty_out(vty, "\n");
2824 }
2825
2826 XFREE(MTYPE_TMP, line);
2827
2828 return ret;
2829 }
2830
2831 static int show_one_daemon(struct vty *vty, struct cmd_token **argv, int argc,
2832 const char *name)
2833 {
2834 int ret;
2835 char *line = do_prepend(vty, argv, argc);
2836
2837 ret = vtysh_client_execute_name(name, line);
2838
2839 XFREE(MTYPE_TMP, line);
2840
2841 return ret;
2842 }
2843
2844 DEFUN (vtysh_show_poll,
2845 vtysh_show_poll_cmd,
2846 "show thread poll",
2847 SHOW_STR
2848 "Thread information\n"
2849 "Thread Poll Information\n")
2850 {
2851 return show_per_daemon(vty, argv, argc, "Thread statistics for %s:\n");
2852 }
2853
2854 DEFUN (vtysh_show_thread,
2855 vtysh_show_thread_cmd,
2856 "show thread cpu [FILTER]",
2857 SHOW_STR
2858 "Thread information\n"
2859 "Thread CPU usage\n"
2860 "Display filter (rwtexb)\n")
2861 {
2862 return show_per_daemon(vty, argv, argc, "Thread statistics for %s:\n");
2863 }
2864
2865 DEFUN (vtysh_show_work_queues,
2866 vtysh_show_work_queues_cmd,
2867 "show work-queues",
2868 SHOW_STR
2869 "Work Queue information\n")
2870 {
2871 return show_per_daemon(vty, argv, argc,
2872 "Work queue statistics for %s:\n");
2873 }
2874
2875 DEFUN (vtysh_show_work_queues_daemon,
2876 vtysh_show_work_queues_daemon_cmd,
2877 "show work-queues " DAEMONS_LIST,
2878 SHOW_STR
2879 "Work Queue information\n"
2880 DAEMONS_STR)
2881 {
2882 return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
2883 }
2884
2885 DEFUNSH(VTYSH_ZEBRA, vtysh_link_params, vtysh_link_params_cmd, "link-params",
2886 LINK_PARAMS_STR)
2887 {
2888 vty->node = LINK_PARAMS_NODE;
2889 return CMD_SUCCESS;
2890 }
2891
2892 DEFUNSH(VTYSH_ZEBRA, exit_link_params, exit_link_params_cmd, "exit-link-params",
2893 "Exit from Link Params configuration node\n")
2894 {
2895 if (vty->node == LINK_PARAMS_NODE)
2896 vty->node = INTERFACE_NODE;
2897 return CMD_SUCCESS;
2898 }
2899
2900 DEFUNSH_HIDDEN (0x00,
2901 vtysh_debug_all,
2902 vtysh_debug_all_cmd,
2903 "[no] debug all",
2904 NO_STR
2905 DEBUG_STR
2906 "Toggle all debugs on or off\n")
2907 {
2908 return CMD_SUCCESS;
2909 }
2910
2911 DEFUN (vtysh_show_debugging,
2912 vtysh_show_debugging_cmd,
2913 "show debugging",
2914 SHOW_STR
2915 DEBUG_STR)
2916 {
2917 return show_per_daemon(vty, argv, argc, "");
2918 }
2919
2920 DEFUN (vtysh_show_debugging_hashtable,
2921 vtysh_show_debugging_hashtable_cmd,
2922 "show debugging hashtable [statistics]",
2923 SHOW_STR
2924 DEBUG_STR
2925 "Statistics about hash tables\n"
2926 "Statistics about hash tables\n")
2927 {
2928 bool stats = strmatch(argv[argc - 1]->text, "statistics");
2929
2930 vty_out(vty, "\n");
2931 vty_out(vty,
2932 "Load factor (LF) - average number of elements across all buckets\n");
2933 vty_out(vty,
2934 "Full load factor (FLF) - average number of elements across full buckets\n\n");
2935 vty_out(vty,
2936 "Standard deviation (SD) is calculated for both the LF and FLF\n");
2937 vty_out(vty,
2938 "and indicates the typical deviation of bucket chain length\n");
2939 vty_out(vty, "from the value in the corresponding load factor.\n\n");
2940
2941 return show_per_daemon(vty, argv, stats ? argc - 1 : argc,
2942 "Hashtable statistics for %s:\n");
2943 }
2944
2945 DEFUN (vtysh_show_error_code,
2946 vtysh_show_error_code_cmd,
2947 "show error <(1-4294967296)|all> [json]",
2948 SHOW_STR
2949 "Information on errors\n"
2950 "Error code to get info about\n"
2951 "Information on all errors\n"
2952 JSON_STR)
2953 {
2954 uint32_t arg = 0;
2955
2956 if (!strmatch(argv[2]->text, "all"))
2957 arg = strtoul(argv[2]->arg, NULL, 10);
2958
2959 /* If it's not a shared code, send it to all the daemons */
2960 if (arg < LIB_FERR_START || arg > LIB_FERR_END) {
2961 show_per_daemon(vty, argv, argc, "");
2962 /* Otherwise, print it ourselves to avoid duplication */
2963 } else {
2964 bool json = strmatch(argv[argc - 1]->text, "json");
2965
2966 if (!strmatch(argv[2]->text, "all"))
2967 arg = strtoul(argv[2]->arg, NULL, 10);
2968
2969 log_ref_display(vty, arg, json);
2970 }
2971
2972 return CMD_SUCCESS;
2973 }
2974
2975 /* Northbound. */
2976 DEFUN_HIDDEN (show_config_running,
2977 show_config_running_cmd,
2978 "show configuration running\
2979 [<json|xml> [translate WORD]]\
2980 [with-defaults]" DAEMONS_LIST,
2981 SHOW_STR
2982 "Configuration information\n"
2983 "Running configuration\n"
2984 "Change output format to JSON\n"
2985 "Change output format to XML\n"
2986 "Translate output\n"
2987 "YANG module translator\n"
2988 "Show default values\n"
2989 DAEMONS_STR)
2990 {
2991 return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
2992 }
2993
2994 DEFUN (show_yang_operational_data,
2995 show_yang_operational_data_cmd,
2996 "show yang operational-data XPATH\
2997 [{\
2998 format <json|xml>\
2999 |translate WORD\
3000 }]" DAEMONS_LIST,
3001 SHOW_STR
3002 "YANG information\n"
3003 "Show YANG operational data\n"
3004 "XPath expression specifying the YANG data path\n"
3005 "Set the output format\n"
3006 "JavaScript Object Notation\n"
3007 "Extensible Markup Language\n"
3008 "Translate operational data\n"
3009 "YANG module translator\n"
3010 DAEMONS_STR)
3011 {
3012 return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
3013 }
3014
3015 DEFUN(show_yang_module, show_yang_module_cmd,
3016 "show yang module [module-translator WORD] " DAEMONS_LIST,
3017 SHOW_STR
3018 "YANG information\n"
3019 "Show loaded modules\n"
3020 "YANG module translator\n"
3021 "YANG module translator\n" DAEMONS_STR)
3022 {
3023 return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
3024 }
3025
3026 DEFUN(show_yang_module_detail, show_yang_module_detail_cmd,
3027 "show yang module\
3028 [module-translator WORD]\
3029 WORD <compiled|summary|tree|yang|yin> " DAEMONS_LIST,
3030 SHOW_STR
3031 "YANG information\n"
3032 "Show loaded modules\n"
3033 "YANG module translator\n"
3034 "YANG module translator\n"
3035 "Module name\n"
3036 "Display compiled module in YANG format\n"
3037 "Display summary information about the module\n"
3038 "Display module in the tree (RFC 8340) format\n"
3039 "Display module in the YANG format\n"
3040 "Display module in the YIN format\n" DAEMONS_STR)
3041 {
3042 return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
3043 }
3044
3045
3046 DEFUNSH(VTYSH_ALL, debug_nb,
3047 debug_nb_cmd,
3048 "[no] debug northbound\
3049 [<\
3050 callbacks [{configuration|state|rpc}]\
3051 |notifications\
3052 |events\
3053 |libyang\
3054 >]",
3055 NO_STR
3056 DEBUG_STR
3057 "Northbound debugging\n"
3058 "Callbacks\n"
3059 "Configuration\n"
3060 "State\n"
3061 "RPC\n"
3062 "Notifications\n"
3063 "Events\n"
3064 "libyang debugging\n")
3065 {
3066 return CMD_SUCCESS;
3067 }
3068
3069 DEFUN (vtysh_show_history,
3070 vtysh_show_history_cmd,
3071 "show history",
3072 SHOW_STR
3073 "The list of commands stored in history\n")
3074 {
3075 HIST_ENTRY **hlist = history_list();
3076 int i = 0;
3077
3078 while (hlist[i]) {
3079 vty_out(vty, "%s\n", hlist[i]->line);
3080 i++;
3081 }
3082 return CMD_SUCCESS;
3083 }
3084
3085 /* Memory */
3086 DEFUN (vtysh_show_memory,
3087 vtysh_show_memory_cmd,
3088 "show memory [" DAEMONS_LIST "]",
3089 SHOW_STR
3090 "Memory statistics\n"
3091 DAEMONS_STR)
3092 {
3093 if (argc == 3)
3094 return show_one_daemon(vty, argv, argc - 1,
3095 argv[argc - 1]->text);
3096
3097 return show_per_daemon(vty, argv, argc, "Memory statistics for %s:\n");
3098 }
3099
3100 DEFUN (vtysh_show_modules,
3101 vtysh_show_modules_cmd,
3102 "show modules",
3103 SHOW_STR
3104 "Loaded modules\n")
3105 {
3106 return show_per_daemon(vty, argv, argc, "Module information for %s:\n");
3107 }
3108
3109 /* Logging commands. */
3110 DEFUN (vtysh_show_logging,
3111 vtysh_show_logging_cmd,
3112 "show logging",
3113 SHOW_STR
3114 "Show current logging configuration\n")
3115 {
3116 return show_per_daemon(vty, argv, argc,
3117 "Logging configuration for %s:\n");
3118 }
3119
3120 DEFUNSH(VTYSH_ALL, vtysh_debug_memstats,
3121 vtysh_debug_memstats_cmd, "[no] debug memstats-at-exit",
3122 NO_STR
3123 "Debug\n"
3124 "Print memory statistics at exit\n")
3125 {
3126 return CMD_SUCCESS;
3127 }
3128
3129 DEFUNSH(VTYSH_ALL, vtysh_service_password_encrypt,
3130 vtysh_service_password_encrypt_cmd, "service password-encryption",
3131 "Set up miscellaneous service\n"
3132 "Enable encrypted passwords\n")
3133 {
3134 return CMD_SUCCESS;
3135 }
3136
3137 DEFUNSH(VTYSH_ALL, no_vtysh_service_password_encrypt,
3138 no_vtysh_service_password_encrypt_cmd, "no service password-encryption",
3139 NO_STR
3140 "Set up miscellaneous service\n"
3141 "Enable encrypted passwords\n")
3142 {
3143 return CMD_SUCCESS;
3144 }
3145
3146 DEFUNSH(VTYSH_ALL, vtysh_config_password, vtysh_password_cmd,
3147 "password [(8-8)] LINE",
3148 "Modify the terminal connection password\n"
3149 "Specifies a HIDDEN password will follow\n"
3150 "The password string\n")
3151 {
3152 return CMD_SUCCESS;
3153 }
3154
3155 DEFUNSH(VTYSH_ALL, no_vtysh_config_password, no_vtysh_password_cmd,
3156 "no password", NO_STR
3157 "Modify the terminal connection password\n")
3158 {
3159 vty_out(vty, NO_PASSWD_CMD_WARNING);
3160
3161 return CMD_SUCCESS;
3162 }
3163
3164 DEFUNSH(VTYSH_ALL, vtysh_config_enable_password, vtysh_enable_password_cmd,
3165 "enable password [(8-8)] LINE",
3166 "Modify enable password parameters\n"
3167 "Assign the privileged level password\n"
3168 "Specifies a HIDDEN password will follow\n"
3169 "The 'enable' password string\n")
3170 {
3171 return CMD_SUCCESS;
3172 }
3173
3174 DEFUNSH(VTYSH_ALL, no_vtysh_config_enable_password,
3175 no_vtysh_enable_password_cmd, "no enable password", NO_STR
3176 "Modify enable password parameters\n"
3177 "Assign the privileged level password\n")
3178 {
3179 vty_out(vty, NO_PASSWD_CMD_WARNING);
3180
3181 return CMD_SUCCESS;
3182 }
3183
3184 DEFUN (vtysh_write_terminal,
3185 vtysh_write_terminal_cmd,
3186 "write terminal ["DAEMONS_LIST"] [no-header]",
3187 "Write running configuration to memory, network, or terminal\n"
3188 "Write to terminal\n"
3189 DAEMONS_STR
3190 "Skip \"Building configuration...\" header\n")
3191 {
3192 unsigned int i;
3193 char line[] = "do write terminal\n";
3194
3195 if (!strcmp(argv[argc - 1]->arg, "no-header"))
3196 argc--;
3197 else {
3198 vty_out(vty, "Building configuration...\n");
3199 vty_out(vty, "\nCurrent configuration:\n");
3200 vty_out(vty, "!\n");
3201 }
3202
3203 for (i = 0; i < array_size(vtysh_client); i++)
3204 if ((argc < 3)
3205 || (strmatch(vtysh_client[i].name, argv[2]->text)))
3206 vtysh_client_config(&vtysh_client[i], line);
3207
3208 /* Integrate vtysh specific configuration. */
3209 vty_open_pager(vty);
3210 vtysh_config_write();
3211 vtysh_config_dump();
3212 vty_close_pager(vty);
3213 vty_out(vty, "end\n");
3214
3215 return CMD_SUCCESS;
3216 }
3217
3218 DEFUN (vtysh_show_running_config,
3219 vtysh_show_running_config_cmd,
3220 "show running-config ["DAEMONS_LIST"] [no-header]",
3221 SHOW_STR
3222 "Current operating configuration\n"
3223 DAEMONS_STR
3224 "Skip \"Building configuration...\" header\n")
3225 {
3226 return vtysh_write_terminal(self, vty, argc, argv);
3227 }
3228
3229 DEFUN (vtysh_integrated_config,
3230 vtysh_integrated_config_cmd,
3231 "service integrated-vtysh-config",
3232 "Set up miscellaneous service\n"
3233 "Write configuration into integrated file\n")
3234 {
3235 vtysh_write_integrated = WRITE_INTEGRATED_YES;
3236 return CMD_SUCCESS;
3237 }
3238
3239 DEFUN (no_vtysh_integrated_config,
3240 no_vtysh_integrated_config_cmd,
3241 "no service integrated-vtysh-config",
3242 NO_STR
3243 "Set up miscellaneous service\n"
3244 "Write configuration into integrated file\n")
3245 {
3246 vtysh_write_integrated = WRITE_INTEGRATED_NO;
3247 return CMD_SUCCESS;
3248 }
3249
3250 static void backup_config_file(const char *fbackup)
3251 {
3252 char *integrate_sav = NULL;
3253
3254 size_t integrate_sav_sz = strlen(fbackup) + strlen(CONF_BACKUP_EXT) + 1;
3255 integrate_sav = malloc(integrate_sav_sz);
3256 strlcpy(integrate_sav, fbackup, integrate_sav_sz);
3257 strlcat(integrate_sav, CONF_BACKUP_EXT, integrate_sav_sz);
3258
3259 /* Move current configuration file to backup config file. */
3260 if (unlink(integrate_sav) != 0 && errno != ENOENT)
3261 vty_out(vty, "Unlink failed for %s: %s\n", integrate_sav,
3262 strerror(errno));
3263 if (rename(fbackup, integrate_sav) != 0 && errno != ENOENT)
3264 vty_out(vty, "Error renaming %s to %s: %s\n", fbackup,
3265 integrate_sav, strerror(errno));
3266 free(integrate_sav);
3267 }
3268
3269 int vtysh_write_config_integrated(void)
3270 {
3271 unsigned int i;
3272 char line[] = "do write terminal\n";
3273 FILE *fp;
3274 int fd;
3275 #ifdef FRR_USER
3276 struct passwd *pwentry;
3277 #endif
3278 #ifdef FRR_GROUP
3279 struct group *grentry;
3280 #endif
3281 uid_t uid = -1;
3282 gid_t gid = -1;
3283 struct stat st;
3284 int err = 0;
3285
3286 vty_out(vty, "Building Configuration...\n");
3287
3288 backup_config_file(frr_config);
3289 fp = fopen(frr_config, "w");
3290 if (fp == NULL) {
3291 vty_out(vty,
3292 "%% Error: failed to open configuration file %s: %s\n",
3293 frr_config, safe_strerror(errno));
3294 return CMD_WARNING_CONFIG_FAILED;
3295 }
3296 fd = fileno(fp);
3297
3298 for (i = 0; i < array_size(vtysh_client); i++)
3299 vtysh_client_config(&vtysh_client[i], line);
3300
3301 vtysh_config_write();
3302 vty->of_saved = vty->of;
3303 vty->of = fp;
3304 vtysh_config_dump();
3305 vty->of = vty->of_saved;
3306
3307 if (fchmod(fd, CONFIGFILE_MASK) != 0) {
3308 printf("%% Warning: can't chmod configuration file %s: %s\n",
3309 frr_config, safe_strerror(errno));
3310 err++;
3311 }
3312
3313 #ifdef FRR_USER
3314 pwentry = getpwnam(FRR_USER);
3315 if (pwentry)
3316 uid = pwentry->pw_uid;
3317 else {
3318 printf("%% Warning: could not look up user \"%s\"\n", FRR_USER);
3319 err++;
3320 }
3321 #endif
3322 #ifdef FRR_GROUP
3323 grentry = getgrnam(FRR_GROUP);
3324 if (grentry)
3325 gid = grentry->gr_gid;
3326 else {
3327 printf("%% Warning: could not look up group \"%s\"\n",
3328 FRR_GROUP);
3329 err++;
3330 }
3331 #endif
3332
3333 if (!fstat(fd, &st)) {
3334 if (st.st_uid == uid)
3335 uid = -1;
3336 if (st.st_gid == gid)
3337 gid = -1;
3338 if ((uid != (uid_t)-1 || gid != (gid_t)-1)
3339 && fchown(fd, uid, gid)) {
3340 printf("%% Warning: can't chown configuration file %s: %s\n",
3341 frr_config, safe_strerror(errno));
3342 err++;
3343 }
3344 } else {
3345 printf("%% Warning: stat() failed on %s: %s\n", frr_config,
3346 safe_strerror(errno));
3347 err++;
3348 }
3349
3350 fclose(fp);
3351
3352 printf("Integrated configuration saved to %s\n", frr_config);
3353 if (err)
3354 return CMD_WARNING;
3355
3356 printf("[OK]\n");
3357 return CMD_SUCCESS;
3358 }
3359
3360 static bool want_config_integrated(void)
3361 {
3362 struct stat s;
3363
3364 switch (vtysh_write_integrated) {
3365 case WRITE_INTEGRATED_UNSPECIFIED:
3366 if (stat(frr_config, &s) && errno == ENOENT)
3367 return false;
3368 return true;
3369 case WRITE_INTEGRATED_NO:
3370 return false;
3371 case WRITE_INTEGRATED_YES:
3372 return true;
3373 }
3374 return true;
3375 }
3376
3377 DEFUN (vtysh_write_memory,
3378 vtysh_write_memory_cmd,
3379 "write [<memory|file>]",
3380 "Write running configuration to memory, network, or terminal\n"
3381 "Write configuration to the file (same as write file)\n"
3382 "Write configuration to the file (same as write memory)\n")
3383 {
3384 int ret = CMD_SUCCESS;
3385 char line[] = "do write memory\n";
3386 unsigned int i;
3387
3388 vty_out(vty, "Note: this version of vtysh never writes vtysh.conf\n");
3389
3390 /* If integrated frr.conf explicitely set. */
3391 if (want_config_integrated()) {
3392 ret = CMD_WARNING_CONFIG_FAILED;
3393
3394 /* first attempt to use watchfrr if it's available */
3395 bool used_watchfrr = false;
3396
3397 for (i = 0; i < array_size(vtysh_client); i++)
3398 if (vtysh_client[i].flag == VTYSH_WATCHFRR)
3399 break;
3400 if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1) {
3401 used_watchfrr = true;
3402 ret = vtysh_client_execute(&vtysh_client[i],
3403 "do write integrated");
3404 }
3405
3406 /*
3407 * If we didn't use watchfrr, fallback to writing the config
3408 * ourselves
3409 */
3410 if (!used_watchfrr) {
3411 printf("\nWarning: attempting direct configuration write without watchfrr.\nFile permissions and ownership may be incorrect, or write may fail.\n\n");
3412 ret = vtysh_write_config_integrated();
3413 }
3414 return ret;
3415 }
3416
3417 vty_out(vty, "Building Configuration...\n");
3418
3419 for (i = 0; i < array_size(vtysh_client); i++)
3420 ret = vtysh_client_execute(&vtysh_client[i], line);
3421
3422 return ret;
3423 }
3424
3425 DEFUN (vtysh_copy_running_config,
3426 vtysh_copy_running_config_cmd,
3427 "copy running-config startup-config",
3428 "Copy from one file to another\n"
3429 "Copy from current system configuration\n"
3430 "Copy to startup configuration\n")
3431 {
3432 return vtysh_write_memory(self, vty, argc, argv);
3433 }
3434
3435 DEFUN (vtysh_copy_to_running,
3436 vtysh_copy_to_running_cmd,
3437 "copy FILENAME running-config",
3438 "Apply a configuration file\n"
3439 "Configuration file to read\n"
3440 "Apply to current configuration\n")
3441 {
3442 int ret;
3443 const char *fname = argv[1]->arg;
3444
3445 ret = vtysh_read_config(fname, true);
3446
3447 /* Return to enable mode - the 'read_config' api leaves us up a level */
3448 vtysh_execute_no_pager("enable");
3449
3450 return ret;
3451 }
3452
3453 DEFUN (vtysh_terminal_paginate,
3454 vtysh_terminal_paginate_cmd,
3455 "[no] terminal paginate",
3456 NO_STR
3457 "Set terminal line parameters\n"
3458 "Use pager for output scrolling\n")
3459 {
3460 free(vtysh_pager_name);
3461 vtysh_pager_name = NULL;
3462
3463 if (strcmp(argv[0]->text, "no"))
3464 vtysh_pager_envdef(true);
3465 return CMD_SUCCESS;
3466 }
3467
3468 DEFUN (vtysh_terminal_length,
3469 vtysh_terminal_length_cmd,
3470 "[no] terminal length (0-4294967295)",
3471 NO_STR
3472 "Set terminal line parameters\n"
3473 "Set number of lines on a screen\n"
3474 "Number of lines on screen (0 for no pausing, nonzero to use pager)\n")
3475 {
3476 int idx_number = 2;
3477 unsigned long lines;
3478
3479 free(vtysh_pager_name);
3480 vtysh_pager_name = NULL;
3481
3482 if (!strcmp(argv[0]->text, "no") || !strcmp(argv[1]->text, "no")) {
3483 /* "terminal no length" = use VTYSH_PAGER */
3484 vtysh_pager_envdef(true);
3485 return CMD_SUCCESS;
3486 }
3487
3488 lines = strtoul(argv[idx_number]->arg, NULL, 10);
3489 if (lines != 0) {
3490 vty_out(vty,
3491 "%% The \"terminal length\" command is deprecated and its value is ignored.\n"
3492 "%% Please use \"terminal paginate\" instead with OS TTY length handling.\n");
3493 vtysh_pager_envdef(true);
3494 }
3495
3496 return CMD_SUCCESS;
3497 }
3498
3499 ALIAS_DEPRECATED(vtysh_terminal_length,
3500 vtysh_terminal_no_length_cmd,
3501 "terminal no length",
3502 "Set terminal line parameters\n"
3503 NO_STR
3504 "Set number of lines on a screen\n")
3505
3506 DEFUN (vtysh_show_daemons,
3507 vtysh_show_daemons_cmd,
3508 "show daemons",
3509 SHOW_STR
3510 "Show list of running daemons\n")
3511 {
3512 unsigned int i;
3513
3514 for (i = 0; i < array_size(vtysh_client); i++)
3515 if (vtysh_client[i].fd >= 0)
3516 vty_out(vty, " %s", vtysh_client[i].name);
3517 vty_out(vty, "\n");
3518
3519 return CMD_SUCCESS;
3520 }
3521
3522 /* Execute command in child process. */
3523 static void execute_command(const char *command, int argc, const char *arg1,
3524 const char *arg2)
3525 {
3526 pid_t pid;
3527 int status;
3528
3529 /* Call fork(). */
3530 pid = fork();
3531
3532 if (pid < 0) {
3533 /* Failure of fork(). */
3534 fprintf(stderr, "Can't fork: %s\n", safe_strerror(errno));
3535 exit(1);
3536 } else if (pid == 0) {
3537 /* This is child process. */
3538 switch (argc) {
3539 case 0:
3540 execlp(command, command, (const char *)NULL);
3541 break;
3542 case 1:
3543 execlp(command, command, arg1, (const char *)NULL);
3544 break;
3545 case 2:
3546 execlp(command, command, arg1, arg2,
3547 (const char *)NULL);
3548 break;
3549 }
3550
3551 /* When execlp suceed, this part is not executed. */
3552 fprintf(stderr, "Can't execute %s: %s\n", command,
3553 safe_strerror(errno));
3554 exit(1);
3555 } else {
3556 /* This is parent. */
3557 execute_flag = 1;
3558 wait4(pid, &status, 0, NULL);
3559 execute_flag = 0;
3560 }
3561 }
3562
3563 DEFUN (vtysh_ping,
3564 vtysh_ping_cmd,
3565 "ping WORD",
3566 "Send echo messages\n"
3567 "Ping destination address or hostname\n")
3568 {
3569 int idx = 1;
3570
3571 argv_find(argv, argc, "WORD", &idx);
3572 execute_command("ping", 1, argv[idx]->arg, NULL);
3573 return CMD_SUCCESS;
3574 }
3575
3576 ALIAS(vtysh_ping, vtysh_ping_ip_cmd, "ping ip WORD",
3577 "Send echo messages\n"
3578 "IP echo\n"
3579 "Ping destination address or hostname\n")
3580
3581 DEFUN (vtysh_traceroute,
3582 vtysh_traceroute_cmd,
3583 "traceroute WORD",
3584 "Trace route to destination\n"
3585 "Trace route to destination address or hostname\n")
3586 {
3587 int idx = 1;
3588
3589 argv_find(argv, argc, "WORD", &idx);
3590 execute_command("traceroute", 1, argv[idx]->arg, NULL);
3591 return CMD_SUCCESS;
3592 }
3593
3594 ALIAS(vtysh_traceroute, vtysh_traceroute_ip_cmd, "traceroute ip WORD",
3595 "Trace route to destination\n"
3596 "IP trace\n"
3597 "Trace route to destination address or hostname\n")
3598
3599 DEFUN (vtysh_mtrace,
3600 vtysh_mtrace_cmd,
3601 "mtrace WORD [WORD]",
3602 "Multicast trace route to multicast source\n"
3603 "Multicast trace route to multicast source address\n"
3604 "Multicast trace route for multicast group address\n")
3605 {
3606 if (argc == 2)
3607 execute_command("mtracebis", 1, argv[1]->arg, NULL);
3608 else
3609 execute_command("mtracebis", 2, argv[1]->arg, argv[2]->arg);
3610 return CMD_SUCCESS;
3611 }
3612
3613 DEFUN (vtysh_ping6,
3614 vtysh_ping6_cmd,
3615 "ping ipv6 WORD",
3616 "Send echo messages\n"
3617 "IPv6 echo\n"
3618 "Ping destination address or hostname\n")
3619 {
3620 execute_command("ping6", 1, argv[2]->arg, NULL);
3621 return CMD_SUCCESS;
3622 }
3623
3624 DEFUN (vtysh_traceroute6,
3625 vtysh_traceroute6_cmd,
3626 "traceroute ipv6 WORD",
3627 "Trace route to destination\n"
3628 "IPv6 trace\n"
3629 "Trace route to destination address or hostname\n")
3630 {
3631 execute_command("traceroute6", 1, argv[2]->arg, NULL);
3632 return CMD_SUCCESS;
3633 }
3634
3635 #if defined(HAVE_SHELL_ACCESS)
3636 DEFUN (vtysh_telnet,
3637 vtysh_telnet_cmd,
3638 "telnet WORD",
3639 "Open a telnet connection\n"
3640 "IP address or hostname of a remote system\n")
3641 {
3642 execute_command("telnet", 1, argv[1]->arg, NULL);
3643 return CMD_SUCCESS;
3644 }
3645
3646 DEFUN (vtysh_telnet_port,
3647 vtysh_telnet_port_cmd,
3648 "telnet WORD PORT",
3649 "Open a telnet connection\n"
3650 "IP address or hostname of a remote system\n"
3651 "TCP Port number\n")
3652 {
3653 execute_command("telnet", 2, argv[1]->arg, argv[2]->arg);
3654 return CMD_SUCCESS;
3655 }
3656
3657 DEFUN (vtysh_ssh,
3658 vtysh_ssh_cmd,
3659 "ssh WORD",
3660 "Open an ssh connection\n"
3661 "[user@]host\n")
3662 {
3663 execute_command("ssh", 1, argv[1]->arg, NULL);
3664 return CMD_SUCCESS;
3665 }
3666
3667 DEFUN (vtysh_start_shell,
3668 vtysh_start_shell_cmd,
3669 "start-shell",
3670 "Start UNIX shell\n")
3671 {
3672 execute_command("sh", 0, NULL, NULL);
3673 return CMD_SUCCESS;
3674 }
3675
3676 DEFUN (vtysh_start_bash,
3677 vtysh_start_bash_cmd,
3678 "start-shell bash",
3679 "Start UNIX shell\n"
3680 "Start bash\n")
3681 {
3682 execute_command("bash", 0, NULL, NULL);
3683 return CMD_SUCCESS;
3684 }
3685
3686 DEFUN (vtysh_start_zsh,
3687 vtysh_start_zsh_cmd,
3688 "start-shell zsh",
3689 "Start UNIX shell\n"
3690 "Start Z shell\n")
3691 {
3692 execute_command("zsh", 0, NULL, NULL);
3693 return CMD_SUCCESS;
3694 }
3695 #endif
3696
3697 DEFUN (config_list,
3698 config_list_cmd,
3699 "list [permutations]",
3700 "Print command list\n"
3701 "Print all possible command permutations\n")
3702 {
3703 return cmd_list_cmds(vty, argc == 2);
3704 }
3705
3706 DEFUN (vtysh_output_file,
3707 vtysh_output_file_cmd,
3708 "output file FILE",
3709 "Direct vtysh output to file\n"
3710 "Direct vtysh output to file\n"
3711 "Path to dump output to\n")
3712 {
3713 const char *path = argv[argc - 1]->arg;
3714 vty->of = fopen(path, "a");
3715 if (!vty->of) {
3716 vty_out(vty, "Failed to open file '%s': %s\n", path,
3717 safe_strerror(errno));
3718 vty->of = stdout;
3719 }
3720 return CMD_SUCCESS;
3721 }
3722
3723 DEFUN (no_vtysh_output_file,
3724 no_vtysh_output_file_cmd,
3725 "no output file [FILE]",
3726 NO_STR
3727 "Direct vtysh output to file\n"
3728 "Direct vtysh output to file\n"
3729 "Path to dump output to\n")
3730 {
3731 if (vty->of != stdout) {
3732 fclose(vty->of);
3733 vty->of = stdout;
3734 }
3735 return CMD_SUCCESS;
3736 }
3737
3738 DEFUN(find,
3739 find_cmd,
3740 "find REGEX...",
3741 "Find CLI command matching a regular expression\n"
3742 "Search pattern (POSIX regex)\n")
3743 {
3744 return cmd_find_cmds(vty, argv, argc);
3745 }
3746
3747 DEFUN_HIDDEN(show_cli_graph_vtysh,
3748 show_cli_graph_vtysh_cmd,
3749 "show cli graph",
3750 SHOW_STR
3751 "CLI reflection\n"
3752 "Dump current command space as DOT graph\n")
3753 {
3754 struct cmd_node *cn = vector_slot(cmdvec, vty->node);
3755 char *dot = cmd_graph_dump_dot(cn->cmdgraph);
3756
3757 vty_out(vty, "%s\n", dot);
3758 XFREE(MTYPE_TMP, dot);
3759 return CMD_SUCCESS;
3760 }
3761
3762 static void vtysh_install_default(enum node_type node)
3763 {
3764 _install_element(node, &config_list_cmd);
3765 _install_element(node, &find_cmd);
3766 _install_element(node, &show_cli_graph_vtysh_cmd);
3767 _install_element(node, &vtysh_output_file_cmd);
3768 _install_element(node, &no_vtysh_output_file_cmd);
3769 }
3770
3771 /* Making connection to protocol daemon. */
3772 static int vtysh_connect(struct vtysh_client *vclient)
3773 {
3774 int ret;
3775 int sock, len;
3776 struct sockaddr_un addr;
3777 struct stat s_stat;
3778 const char *path;
3779
3780 if (!vclient->path[0])
3781 snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty",
3782 vtydir, vclient->name);
3783 path = vclient->path;
3784
3785 /* Stat socket to see if we have permission to access it. */
3786 ret = stat(path, &s_stat);
3787 if (ret < 0 && errno != ENOENT) {
3788 fprintf(stderr, "vtysh_connect(%s): stat = %s\n", path,
3789 safe_strerror(errno));
3790 exit(1);
3791 }
3792
3793 if (ret >= 0) {
3794 if (!S_ISSOCK(s_stat.st_mode)) {
3795 fprintf(stderr, "vtysh_connect(%s): Not a socket\n",
3796 path);
3797 exit(1);
3798 }
3799 }
3800
3801 sock = socket(AF_UNIX, SOCK_STREAM, 0);
3802 if (sock < 0) {
3803 #ifdef DEBUG
3804 fprintf(stderr, "vtysh_connect(%s): socket = %s\n", path,
3805 safe_strerror(errno));
3806 #endif /* DEBUG */
3807 return -1;
3808 }
3809
3810 memset(&addr, 0, sizeof(struct sockaddr_un));
3811 addr.sun_family = AF_UNIX;
3812 strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
3813 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
3814 len = addr.sun_len = SUN_LEN(&addr);
3815 #else
3816 len = sizeof(addr.sun_family) + strlen(addr.sun_path);
3817 #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
3818
3819 ret = connect(sock, (struct sockaddr *)&addr, len);
3820 if (ret < 0) {
3821 #ifdef DEBUG
3822 fprintf(stderr, "vtysh_connect(%s): connect = %s\n", path,
3823 safe_strerror(errno));
3824 #endif /* DEBUG */
3825 close(sock);
3826 return -1;
3827 }
3828 vclient->fd = sock;
3829
3830 return 0;
3831 }
3832
3833 static int vtysh_reconnect(struct vtysh_client *vclient)
3834 {
3835 int ret;
3836
3837 fprintf(stderr, "Warning: connecting to %s...", vclient->name);
3838 ret = vtysh_connect(vclient);
3839 if (ret < 0) {
3840 fprintf(stderr, "failed!\n");
3841 return ret;
3842 }
3843 fprintf(stderr, "success!\n");
3844 if (vtysh_client_execute(vclient, "enable") < 0)
3845 return -1;
3846 return vtysh_execute_no_pager("end");
3847 }
3848
3849 /* Return true if str ends with suffix, else return false */
3850 static int ends_with(const char *str, const char *suffix)
3851 {
3852 if (!str || !suffix)
3853 return 0;
3854 size_t lenstr = strlen(str);
3855 size_t lensuffix = strlen(suffix);
3856 if (lensuffix > lenstr)
3857 return 0;
3858 return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
3859 }
3860
3861 static void vtysh_client_sorted_insert(struct vtysh_client *head_client,
3862 struct vtysh_client *client)
3863 {
3864 struct vtysh_client *prev_node, *current_node;
3865
3866 prev_node = head_client;
3867 current_node = head_client->next;
3868 while (current_node) {
3869 if (strcmp(current_node->path, client->path) > 0)
3870 break;
3871
3872 prev_node = current_node;
3873 current_node = current_node->next;
3874 }
3875 client->next = current_node;
3876 prev_node->next = client;
3877 }
3878
3879 #define MAXIMUM_INSTANCES 10
3880
3881 static void vtysh_update_all_instances(struct vtysh_client *head_client)
3882 {
3883 struct vtysh_client *client;
3884 DIR *dir;
3885 struct dirent *file;
3886 int n = 0;
3887
3888 if (head_client->flag != VTYSH_OSPFD)
3889 return;
3890
3891 /* ls vty_sock_dir and look for all files ending in .vty */
3892 dir = opendir(vtydir);
3893 if (dir) {
3894 while ((file = readdir(dir)) != NULL) {
3895 if (frrstr_startswith(file->d_name, "ospfd-")
3896 && ends_with(file->d_name, ".vty")) {
3897 if (n == MAXIMUM_INSTANCES) {
3898 fprintf(stderr,
3899 "Parsing %s, client limit(%d) reached!\n",
3900 vtydir, n);
3901 break;
3902 }
3903 client = (struct vtysh_client *)malloc(
3904 sizeof(struct vtysh_client));
3905 client->fd = -1;
3906 client->name = "ospfd";
3907 client->flag = VTYSH_OSPFD;
3908 snprintf(client->path, sizeof(client->path),
3909 "%s/%s", vtydir, file->d_name);
3910 client->next = NULL;
3911 vtysh_client_sorted_insert(head_client, client);
3912 n++;
3913 }
3914 }
3915 closedir(dir);
3916 }
3917 }
3918
3919 static int vtysh_connect_all_instances(struct vtysh_client *head_client)
3920 {
3921 struct vtysh_client *client;
3922 int rc = 0;
3923
3924 vtysh_update_all_instances(head_client);
3925
3926 client = head_client->next;
3927 while (client) {
3928 if (vtysh_connect(client) == 0)
3929 rc++;
3930 client = client->next;
3931 }
3932
3933 return rc;
3934 }
3935
3936 int vtysh_connect_all(const char *daemon_name)
3937 {
3938 unsigned int i;
3939 int rc = 0;
3940 int matches = 0;
3941
3942 for (i = 0; i < array_size(vtysh_client); i++) {
3943 if (!daemon_name
3944 || !strcmp(daemon_name, vtysh_client[i].name)) {
3945 matches++;
3946 if (vtysh_connect(&vtysh_client[i]) == 0)
3947 rc++;
3948
3949 rc += vtysh_connect_all_instances(&vtysh_client[i]);
3950 }
3951 }
3952 if (!matches)
3953 fprintf(stderr, "Error: no daemons match name %s!\n",
3954 daemon_name);
3955 return rc;
3956 }
3957
3958 /* To disable readline's filename completion. */
3959 static char *vtysh_completion_entry_function(const char *ignore,
3960 int invoking_key)
3961 {
3962 return NULL;
3963 }
3964
3965 void vtysh_readline_init(void)
3966 {
3967 /* readline related settings. */
3968 char *disable_bracketed_paste =
3969 XSTRDUP(MTYPE_TMP, "set enable-bracketed-paste off");
3970
3971 rl_initialize();
3972 rl_parse_and_bind(disable_bracketed_paste);
3973 rl_bind_key('?', (rl_command_func_t *)vtysh_rl_describe);
3974 rl_completion_entry_function = vtysh_completion_entry_function;
3975 rl_attempted_completion_function = new_completion;
3976
3977 XFREE(MTYPE_TMP, disable_bracketed_paste);
3978 }
3979
3980 char *vtysh_prompt(void)
3981 {
3982 static char buf[512];
3983
3984 snprintf(buf, sizeof(buf), cmd_prompt(vty->node), cmd_hostname_get());
3985 return buf;
3986 }
3987
3988 static void vtysh_ac_line(void *arg, const char *line)
3989 {
3990 vector comps = arg;
3991 size_t i;
3992 for (i = 0; i < vector_active(comps); i++)
3993 if (!strcmp(line, (char *)vector_slot(comps, i)))
3994 return;
3995 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, line));
3996 }
3997
3998 static void vtysh_autocomplete(vector comps, struct cmd_token *token)
3999 {
4000 char accmd[256];
4001 size_t i;
4002
4003 snprintf(accmd, sizeof(accmd), "autocomplete %d %s %s", token->type,
4004 token->text, token->varname ? token->varname : "-");
4005
4006 vty->of_saved = vty->of;
4007 vty->of = NULL;
4008 for (i = 0; i < array_size(vtysh_client); i++)
4009 vtysh_client_run_all(&vtysh_client[i], accmd, 1, vtysh_ac_line,
4010 comps);
4011 vty->of = vty->of_saved;
4012 }
4013
4014 static const struct cmd_variable_handler vtysh_var_handler[] = {
4015 {/* match all */
4016 .tokenname = NULL,
4017 .varname = NULL,
4018 .completions = vtysh_autocomplete},
4019 {.completions = NULL}};
4020
4021 void vtysh_uninit(void)
4022 {
4023 if (vty->of != stdout)
4024 fclose(vty->of);
4025 }
4026
4027 void vtysh_init_vty(void)
4028 {
4029 /* Make vty structure. */
4030 vty = vty_new();
4031 vty->type = VTY_SHELL;
4032 vty->node = VIEW_NODE;
4033
4034 /* set default output */
4035 vty->of = stdout;
4036 vtysh_pager_envdef(false);
4037
4038 /* Initialize commands. */
4039 cmd_init(0);
4040 cmd_variable_handler_register(vtysh_var_handler);
4041
4042 /* bgpd */
4043 #ifdef HAVE_BGPD
4044 install_node(&bgp_node);
4045 install_element(CONFIG_NODE, &router_bgp_cmd);
4046 install_element(BGP_NODE, &vtysh_exit_bgpd_cmd);
4047 install_element(BGP_NODE, &vtysh_quit_bgpd_cmd);
4048 install_element(BGP_NODE, &vtysh_end_all_cmd);
4049
4050 install_node(&bgp_vpnv4_node);
4051 install_element(BGP_NODE, &address_family_ipv4_vpn_cmd);
4052 #ifdef KEEP_OLD_VPN_COMMANDS
4053 install_element(BGP_NODE, &address_family_vpnv4_cmd);
4054 #endif /* KEEP_OLD_VPN_COMMANDS */
4055 install_element(BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd);
4056 install_element(BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd);
4057 install_element(BGP_VPNV4_NODE, &vtysh_end_all_cmd);
4058 install_element(BGP_VPNV4_NODE, &exit_address_family_cmd);
4059
4060 install_node(&bgp_vpnv6_node);
4061 install_element(BGP_NODE, &address_family_ipv6_vpn_cmd);
4062 #ifdef KEEP_OLD_VPN_COMMANDS
4063 install_element(BGP_NODE, &address_family_vpnv6_cmd);
4064 #endif /* KEEP_OLD_VPN_COMMANDS */
4065 install_element(BGP_VPNV6_NODE, &vtysh_exit_bgpd_cmd);
4066 install_element(BGP_VPNV6_NODE, &vtysh_quit_bgpd_cmd);
4067 install_element(BGP_VPNV6_NODE, &vtysh_end_all_cmd);
4068 install_element(BGP_VPNV6_NODE, &exit_address_family_cmd);
4069
4070 install_node(&bgp_flowspecv4_node);
4071 install_element(BGP_NODE, &address_family_flowspecv4_cmd);
4072 install_element(BGP_FLOWSPECV4_NODE, &vtysh_exit_bgpd_cmd);
4073 install_element(BGP_FLOWSPECV4_NODE, &vtysh_quit_bgpd_cmd);
4074 install_element(BGP_FLOWSPECV4_NODE, &vtysh_end_all_cmd);
4075 install_element(BGP_FLOWSPECV4_NODE, &exit_address_family_cmd);
4076
4077 install_node(&bgp_flowspecv6_node);
4078 install_element(BGP_NODE, &address_family_flowspecv6_cmd);
4079 install_element(BGP_FLOWSPECV6_NODE, &vtysh_exit_bgpd_cmd);
4080 install_element(BGP_FLOWSPECV6_NODE, &vtysh_quit_bgpd_cmd);
4081 install_element(BGP_FLOWSPECV6_NODE, &vtysh_end_all_cmd);
4082 install_element(BGP_FLOWSPECV6_NODE, &exit_address_family_cmd);
4083
4084 install_node(&bgp_ipv4_node);
4085 install_element(BGP_NODE, &address_family_ipv4_cmd);
4086 install_element(BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd);
4087 install_element(BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd);
4088 install_element(BGP_IPV4_NODE, &vtysh_end_all_cmd);
4089 install_element(BGP_IPV4_NODE, &exit_address_family_cmd);
4090
4091 install_node(&bgp_ipv4m_node);
4092 install_element(BGP_NODE, &address_family_ipv4_multicast_cmd);
4093 install_element(BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd);
4094 install_element(BGP_IPV4M_NODE, &vtysh_quit_bgpd_cmd);
4095 install_element(BGP_IPV4M_NODE, &vtysh_end_all_cmd);
4096 install_element(BGP_IPV4M_NODE, &exit_address_family_cmd);
4097
4098 install_node(&bgp_ipv4l_node);
4099 install_element(BGP_NODE, &address_family_ipv4_labeled_unicast_cmd);
4100 install_element(BGP_IPV4L_NODE, &vtysh_exit_bgpd_cmd);
4101 install_element(BGP_IPV4L_NODE, &vtysh_quit_bgpd_cmd);
4102 install_element(BGP_IPV4L_NODE, &vtysh_end_all_cmd);
4103 install_element(BGP_IPV4L_NODE, &exit_address_family_cmd);
4104
4105 install_node(&bgp_ipv6_node);
4106 install_element(BGP_NODE, &address_family_ipv6_cmd);
4107 install_element(BGP_IPV6_NODE, &vtysh_exit_bgpd_cmd);
4108 install_element(BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd);
4109 install_element(BGP_IPV6_NODE, &vtysh_end_all_cmd);
4110 install_element(BGP_IPV6_NODE, &exit_address_family_cmd);
4111
4112 install_node(&bgp_ipv6m_node);
4113 install_element(BGP_NODE, &address_family_ipv6_multicast_cmd);
4114 install_element(BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd);
4115 install_element(BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd);
4116 install_element(BGP_IPV6M_NODE, &vtysh_end_all_cmd);
4117 install_element(BGP_IPV6M_NODE, &exit_address_family_cmd);
4118
4119 install_node(&bgp_ipv6l_node);
4120 install_element(BGP_NODE, &address_family_ipv6_labeled_unicast_cmd);
4121 install_element(BGP_IPV6L_NODE, &vtysh_exit_bgpd_cmd);
4122 install_element(BGP_IPV6L_NODE, &vtysh_quit_bgpd_cmd);
4123 install_element(BGP_IPV6L_NODE, &vtysh_end_all_cmd);
4124 install_element(BGP_IPV6L_NODE, &exit_address_family_cmd);
4125
4126 #if defined(ENABLE_BGP_VNC)
4127 install_node(&bgp_vrf_policy_node);
4128 install_element(BGP_NODE, &vnc_vrf_policy_cmd);
4129 install_element(BGP_VRF_POLICY_NODE, &vtysh_exit_bgpd_cmd);
4130 install_element(BGP_VRF_POLICY_NODE, &vtysh_quit_bgpd_cmd);
4131 install_element(BGP_VRF_POLICY_NODE, &vtysh_end_all_cmd);
4132 install_element(BGP_VRF_POLICY_NODE, &exit_vrf_policy_cmd);
4133
4134 install_node(&bgp_vnc_defaults_node);
4135 install_element(BGP_NODE, &vnc_defaults_cmd);
4136 install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_exit_bgpd_cmd);
4137 install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_quit_bgpd_cmd);
4138 install_element(BGP_VNC_DEFAULTS_NODE, &vtysh_end_all_cmd);
4139 install_element(BGP_VNC_DEFAULTS_NODE, &exit_vnc_config_cmd);
4140
4141 install_node(&bgp_vnc_nve_group_node);
4142 install_element(BGP_NODE, &vnc_nve_group_cmd);
4143 install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_exit_bgpd_cmd);
4144 install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_quit_bgpd_cmd);
4145 install_element(BGP_VNC_NVE_GROUP_NODE, &vtysh_end_all_cmd);
4146 install_element(BGP_VNC_NVE_GROUP_NODE, &exit_vnc_config_cmd);
4147
4148 install_node(&bgp_vnc_l2_group_node);
4149 install_element(BGP_NODE, &vnc_l2_group_cmd);
4150 install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_exit_bgpd_cmd);
4151 install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_quit_bgpd_cmd);
4152 install_element(BGP_VNC_L2_GROUP_NODE, &vtysh_end_all_cmd);
4153 install_element(BGP_VNC_L2_GROUP_NODE, &exit_vnc_config_cmd);
4154 #endif
4155
4156 install_node(&bgp_evpn_node);
4157 install_element(BGP_NODE, &address_family_evpn_cmd);
4158 #if defined(HAVE_CUMULUS)
4159 install_element(BGP_NODE, &address_family_evpn2_cmd);
4160 #endif
4161 install_element(BGP_EVPN_NODE, &vtysh_quit_bgpd_cmd);
4162 install_element(BGP_EVPN_NODE, &vtysh_exit_bgpd_cmd);
4163 install_element(BGP_EVPN_NODE, &vtysh_end_all_cmd);
4164 install_element(BGP_EVPN_NODE, &exit_address_family_cmd);
4165
4166 install_node(&bgp_evpn_vni_node);
4167 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
4168 install_element(BGP_EVPN_VNI_NODE, &vtysh_exit_bgpd_cmd);
4169 install_element(BGP_EVPN_VNI_NODE, &vtysh_quit_bgpd_cmd);
4170 install_element(BGP_EVPN_VNI_NODE, &vtysh_end_all_cmd);
4171 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
4172
4173 install_node(&rpki_node);
4174 install_element(CONFIG_NODE, &rpki_cmd);
4175 install_element(RPKI_NODE, &rpki_exit_cmd);
4176 install_element(RPKI_NODE, &rpki_quit_cmd);
4177 install_element(RPKI_NODE, &vtysh_end_all_cmd);
4178
4179 install_node(&bmp_node);
4180 install_element(BGP_NODE, &bmp_targets_cmd);
4181 install_element(BMP_NODE, &bmp_exit_cmd);
4182 install_element(BMP_NODE, &bmp_quit_cmd);
4183 install_element(BMP_NODE, &vtysh_end_all_cmd);
4184
4185 install_node(&bgp_srv6_node);
4186 install_element(BGP_NODE, &bgp_srv6_cmd);
4187 install_element(BGP_SRV6_NODE, &exit_bgp_srv6_cmd);
4188 install_element(BGP_SRV6_NODE, &quit_bgp_srv6_cmd);
4189 install_element(BGP_SRV6_NODE, &vtysh_end_all_cmd);
4190 #endif /* HAVE_BGPD */
4191
4192 /* ripd */
4193 install_node(&rip_node);
4194 #ifdef HAVE_RIPD
4195 install_element(CONFIG_NODE, &router_rip_cmd);
4196 install_element(RIP_NODE, &vtysh_exit_ripd_cmd);
4197 install_element(RIP_NODE, &vtysh_quit_ripd_cmd);
4198 install_element(RIP_NODE, &vtysh_end_all_cmd);
4199 #endif /* HAVE_RIPD */
4200
4201 /* ripngd */
4202 install_node(&ripng_node);
4203 #ifdef HAVE_RIPNGD
4204 install_element(CONFIG_NODE, &router_ripng_cmd);
4205 install_element(RIPNG_NODE, &vtysh_exit_ripngd_cmd);
4206 install_element(RIPNG_NODE, &vtysh_quit_ripngd_cmd);
4207 install_element(RIPNG_NODE, &vtysh_end_all_cmd);
4208 #endif /* HAVE_RIPNGD */
4209
4210 /* ospfd */
4211 #ifdef HAVE_OSPFD
4212 install_node(&ospf_node);
4213 install_element(CONFIG_NODE, &router_ospf_cmd);
4214 install_element(OSPF_NODE, &vtysh_exit_ospfd_cmd);
4215 install_element(OSPF_NODE, &vtysh_quit_ospfd_cmd);
4216 install_element(OSPF_NODE, &vtysh_end_all_cmd);
4217 #endif /* HAVE_OSPFD */
4218
4219 /* ospf6d */
4220 #ifdef HAVE_OSPF6D
4221 install_node(&ospf6_node);
4222 install_element(CONFIG_NODE, &router_ospf6_cmd);
4223 install_element(OSPF6_NODE, &vtysh_exit_ospf6d_cmd);
4224 install_element(OSPF6_NODE, &vtysh_quit_ospf6d_cmd);
4225 install_element(OSPF6_NODE, &vtysh_end_all_cmd);
4226 #endif /* HAVE_OSPF6D */
4227
4228 /* ldpd */
4229 #if defined(HAVE_LDPD)
4230 install_node(&ldp_node);
4231 install_element(CONFIG_NODE, &ldp_mpls_ldp_cmd);
4232 install_element(LDP_NODE, &vtysh_exit_ldpd_cmd);
4233 install_element(LDP_NODE, &vtysh_quit_ldpd_cmd);
4234 install_element(LDP_NODE, &vtysh_end_all_cmd);
4235
4236 install_node(&ldp_ipv4_node);
4237 install_element(LDP_NODE, &ldp_address_family_ipv4_cmd);
4238 install_element(LDP_IPV4_NODE, &vtysh_exit_ldpd_cmd);
4239 install_element(LDP_IPV4_NODE, &vtysh_quit_ldpd_cmd);
4240 install_element(LDP_IPV4_NODE, &ldp_exit_address_family_cmd);
4241 install_element(LDP_IPV4_NODE, &vtysh_end_all_cmd);
4242
4243 install_node(&ldp_ipv6_node);
4244 install_element(LDP_NODE, &ldp_address_family_ipv6_cmd);
4245 install_element(LDP_IPV6_NODE, &vtysh_exit_ldpd_cmd);
4246 install_element(LDP_IPV6_NODE, &vtysh_quit_ldpd_cmd);
4247 install_element(LDP_IPV6_NODE, &ldp_exit_address_family_cmd);
4248 install_element(LDP_IPV6_NODE, &vtysh_end_all_cmd);
4249
4250 install_node(&ldp_ipv4_iface_node);
4251 install_element(LDP_IPV4_NODE, &ldp_interface_ifname_cmd);
4252 install_element(LDP_IPV4_IFACE_NODE, &vtysh_exit_ldpd_cmd);
4253 install_element(LDP_IPV4_IFACE_NODE, &vtysh_quit_ldpd_cmd);
4254 install_element(LDP_IPV4_IFACE_NODE, &vtysh_end_all_cmd);
4255
4256 install_node(&ldp_ipv6_iface_node);
4257 install_element(LDP_IPV6_NODE, &ldp_interface_ifname_cmd);
4258 install_element(LDP_IPV6_IFACE_NODE, &vtysh_exit_ldpd_cmd);
4259 install_element(LDP_IPV6_IFACE_NODE, &vtysh_quit_ldpd_cmd);
4260 install_element(LDP_IPV6_IFACE_NODE, &vtysh_end_all_cmd);
4261
4262 install_node(&ldp_l2vpn_node);
4263 install_element(CONFIG_NODE, &ldp_l2vpn_word_type_vpls_cmd);
4264 install_element(LDP_L2VPN_NODE, &vtysh_exit_ldpd_cmd);
4265 install_element(LDP_L2VPN_NODE, &vtysh_quit_ldpd_cmd);
4266 install_element(LDP_L2VPN_NODE, &vtysh_end_all_cmd);
4267
4268 install_node(&ldp_pseudowire_node);
4269 install_element(LDP_L2VPN_NODE, &ldp_member_pseudowire_ifname_cmd);
4270 install_element(LDP_PSEUDOWIRE_NODE, &vtysh_exit_ldpd_cmd);
4271 install_element(LDP_PSEUDOWIRE_NODE, &vtysh_quit_ldpd_cmd);
4272 install_element(LDP_PSEUDOWIRE_NODE, &vtysh_end_all_cmd);
4273 #endif
4274
4275 /* eigrpd */
4276 #ifdef HAVE_EIGRPD
4277 install_node(&eigrp_node);
4278 install_element(CONFIG_NODE, &router_eigrp_cmd);
4279 install_element(EIGRP_NODE, &vtysh_exit_eigrpd_cmd);
4280 install_element(EIGRP_NODE, &vtysh_quit_eigrpd_cmd);
4281 install_element(EIGRP_NODE, &vtysh_end_all_cmd);
4282 #endif /* HAVE_EIGRPD */
4283
4284 /* babeld */
4285 #ifdef HAVE_BABELD
4286 install_node(&babel_node);
4287 install_element(CONFIG_NODE, &router_babel_cmd);
4288 install_element(BABEL_NODE, &vtysh_exit_babeld_cmd);
4289 install_element(BABEL_NODE, &vtysh_quit_babeld_cmd);
4290 install_element(BABEL_NODE, &vtysh_end_all_cmd);
4291 #endif /* HAVE_BABELD */
4292
4293 /* isisd */
4294 #ifdef HAVE_ISISD
4295 install_node(&isis_node);
4296 install_element(CONFIG_NODE, &router_isis_cmd);
4297 install_element(ISIS_NODE, &vtysh_exit_isisd_cmd);
4298 install_element(ISIS_NODE, &vtysh_quit_isisd_cmd);
4299 install_element(ISIS_NODE, &vtysh_end_all_cmd);
4300 #endif /* HAVE_ISISD */
4301
4302 /* fabricd */
4303 #ifdef HAVE_FABRICD
4304 install_node(&openfabric_node);
4305 install_element(CONFIG_NODE, &router_openfabric_cmd);
4306 install_element(OPENFABRIC_NODE, &vtysh_exit_fabricd_cmd);
4307 install_element(OPENFABRIC_NODE, &vtysh_quit_fabricd_cmd);
4308 install_element(OPENFABRIC_NODE, &vtysh_end_all_cmd);
4309 #endif /* HAVE_FABRICD */
4310
4311 /* pbrd */
4312 #ifdef HAVE_PBRD
4313 install_node(&pbr_map_node);
4314 install_element(CONFIG_NODE, &vtysh_pbr_map_cmd);
4315 install_element(CONFIG_NODE, &vtysh_no_pbr_map_cmd);
4316 install_element(PBRMAP_NODE, &vtysh_exit_pbr_map_cmd);
4317 install_element(PBRMAP_NODE, &vtysh_quit_pbr_map_cmd);
4318 install_element(PBRMAP_NODE, &vtysh_end_all_cmd);
4319 #endif /* HAVE_PBRD */
4320
4321 /* bfdd */
4322 #if HAVE_BFDD > 0
4323 install_node(&bfd_node);
4324 install_element(CONFIG_NODE, &bfd_enter_cmd);
4325 install_element(BFD_NODE, &vtysh_exit_bfdd_cmd);
4326 install_element(BFD_NODE, &vtysh_quit_bfdd_cmd);
4327 install_element(BFD_NODE, &vtysh_end_all_cmd);
4328
4329 install_node(&bfd_peer_node);
4330 install_element(BFD_NODE, &bfd_peer_enter_cmd);
4331 install_element(BFD_PEER_NODE, &vtysh_exit_bfdd_cmd);
4332 install_element(BFD_PEER_NODE, &vtysh_quit_bfdd_cmd);
4333 install_element(BFD_PEER_NODE, &vtysh_end_all_cmd);
4334
4335 install_node(&bfd_profile_node);
4336 install_element(BFD_NODE, &bfd_profile_enter_cmd);
4337 install_element(BFD_PROFILE_NODE, &vtysh_exit_bfdd_cmd);
4338 install_element(BFD_PROFILE_NODE, &vtysh_quit_bfdd_cmd);
4339 install_element(BFD_PROFILE_NODE, &vtysh_end_all_cmd);
4340 #endif /* HAVE_BFDD */
4341
4342 install_node(&segment_routing_node);
4343 install_element(SEGMENT_ROUTING_NODE, &vtysh_exit_sr_cmd);
4344 install_element(SEGMENT_ROUTING_NODE, &vtysh_quit_sr_cmd);
4345 install_element(SEGMENT_ROUTING_NODE, &vtysh_end_all_cmd);
4346
4347 #if defined(HAVE_PATHD)
4348 install_node(&sr_traffic_eng_node);
4349 install_node(&srte_segment_list_node);
4350 install_node(&srte_policy_node);
4351 install_node(&srte_candidate_dyn_node);
4352
4353 install_element(SR_TRAFFIC_ENG_NODE, &vtysh_exit_pathd_cmd);
4354 install_element(SR_TRAFFIC_ENG_NODE, &vtysh_quit_pathd_cmd);
4355 install_element(SR_SEGMENT_LIST_NODE, &vtysh_exit_pathd_cmd);
4356 install_element(SR_SEGMENT_LIST_NODE, &vtysh_quit_pathd_cmd);
4357 install_element(SR_POLICY_NODE, &vtysh_exit_pathd_cmd);
4358 install_element(SR_POLICY_NODE, &vtysh_quit_pathd_cmd);
4359 install_element(SR_CANDIDATE_DYN_NODE, &vtysh_exit_pathd_cmd);
4360 install_element(SR_CANDIDATE_DYN_NODE, &vtysh_quit_pathd_cmd);
4361
4362
4363 install_element(SR_TRAFFIC_ENG_NODE, &vtysh_end_all_cmd);
4364 install_element(SR_SEGMENT_LIST_NODE, &vtysh_end_all_cmd);
4365 install_element(SR_POLICY_NODE, &vtysh_end_all_cmd);
4366 install_element(SR_CANDIDATE_DYN_NODE, &vtysh_end_all_cmd);
4367
4368 install_element(CONFIG_NODE, &segment_routing_cmd);
4369 install_element(SEGMENT_ROUTING_NODE, &sr_traffic_eng_cmd);
4370 install_element(SR_TRAFFIC_ENG_NODE, &srte_segment_list_cmd);
4371 install_element(SR_TRAFFIC_ENG_NODE, &srte_policy_cmd);
4372 install_element(SR_POLICY_NODE, &srte_policy_candidate_dyn_path_cmd);
4373
4374 #if defined(HAVE_PATHD_PCEP)
4375 install_node(&pcep_node);
4376 install_node(&pcep_pcc_node);
4377 install_node(&pcep_pce_node);
4378 install_node(&pcep_pce_config_node);
4379
4380 install_element(PCEP_NODE, &vtysh_exit_pathd_cmd);
4381 install_element(PCEP_NODE, &vtysh_quit_pathd_cmd);
4382 install_element(PCEP_PCC_NODE, &vtysh_exit_pathd_cmd);
4383 install_element(PCEP_PCC_NODE, &vtysh_quit_pathd_cmd);
4384 install_element(PCEP_PCE_NODE, &vtysh_exit_pathd_cmd);
4385 install_element(PCEP_PCE_NODE, &vtysh_quit_pathd_cmd);
4386 install_element(PCEP_PCE_CONFIG_NODE, &vtysh_exit_pathd_cmd);
4387 install_element(PCEP_PCE_CONFIG_NODE, &vtysh_quit_pathd_cmd);
4388
4389 install_element(PCEP_NODE, &vtysh_end_all_cmd);
4390 install_element(PCEP_PCC_NODE, &vtysh_end_all_cmd);
4391 install_element(PCEP_PCE_NODE, &vtysh_end_all_cmd);
4392 install_element(PCEP_PCE_CONFIG_NODE, &vtysh_end_all_cmd);
4393
4394 install_element(SR_TRAFFIC_ENG_NODE, &pcep_cmd);
4395 install_element(PCEP_NODE, &pcep_cli_pcc_cmd);
4396 install_element(PCEP_NODE, &pcep_cli_pcep_pce_config_cmd);
4397 install_element(PCEP_NODE, &pcep_cli_pce_cmd);
4398 #endif /* HAVE_PATHD_PCEP */
4399
4400 #endif /* HAVE_PATHD */
4401
4402 /* keychain */
4403 install_node(&keychain_node);
4404 install_element(CONFIG_NODE, &key_chain_cmd);
4405 install_element(KEYCHAIN_NODE, &key_chain_cmd);
4406 install_element(KEYCHAIN_NODE, &vtysh_exit_keys_cmd);
4407 install_element(KEYCHAIN_NODE, &vtysh_quit_keys_cmd);
4408 install_element(KEYCHAIN_NODE, &vtysh_end_all_cmd);
4409
4410 install_node(&keychain_key_node);
4411 install_element(KEYCHAIN_NODE, &key_cmd);
4412 install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd);
4413 install_element(KEYCHAIN_KEY_NODE, &vtysh_exit_keys_cmd);
4414 install_element(KEYCHAIN_KEY_NODE, &vtysh_quit_keys_cmd);
4415 install_element(KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
4416
4417 /* nexthop-group */
4418 install_node(&nh_group_node);
4419 install_element(CONFIG_NODE, &vtysh_nexthop_group_cmd);
4420 install_element(CONFIG_NODE, &vtysh_no_nexthop_group_cmd);
4421 install_element(NH_GROUP_NODE, &vtysh_end_all_cmd);
4422 install_element(NH_GROUP_NODE, &vtysh_exit_nexthop_group_cmd);
4423 install_element(NH_GROUP_NODE, &vtysh_quit_nexthop_group_cmd);
4424
4425 /* zebra and all */
4426 install_node(&zebra_node);
4427
4428 install_node(&interface_node);
4429 install_element(CONFIG_NODE, &vtysh_interface_cmd);
4430 install_element(INTERFACE_NODE, &vtysh_end_all_cmd);
4431 install_element(INTERFACE_NODE, &vtysh_exit_interface_cmd);
4432 install_element(INTERFACE_NODE, &vtysh_quit_interface_cmd);
4433
4434 install_node(&link_params_node);
4435 install_element(INTERFACE_NODE, &vtysh_link_params_cmd);
4436 install_element(LINK_PARAMS_NODE, &exit_link_params_cmd);
4437 install_element(LINK_PARAMS_NODE, &vtysh_end_all_cmd);
4438 install_element(LINK_PARAMS_NODE, &vtysh_exit_interface_cmd);
4439
4440 install_node(&pw_node);
4441 install_element(CONFIG_NODE, &vtysh_pseudowire_cmd);
4442 install_element(PW_NODE, &vtysh_end_all_cmd);
4443 install_element(PW_NODE, &vtysh_exit_interface_cmd);
4444 install_element(PW_NODE, &vtysh_quit_interface_cmd);
4445
4446 install_node(&vrf_node);
4447 install_element(CONFIG_NODE, &vtysh_vrf_cmd);
4448 install_element(VRF_NODE, &vtysh_vrf_netns_cmd);
4449 install_element(VRF_NODE, &vtysh_no_vrf_netns_cmd);
4450 install_element(VRF_NODE, &exit_vrf_config_cmd);
4451 install_element(VRF_NODE, &vtysh_end_all_cmd);
4452 install_element(VRF_NODE, &vtysh_exit_vrf_cmd);
4453 install_element(VRF_NODE, &vtysh_quit_vrf_cmd);
4454
4455 install_node(&rmap_node);
4456 install_element(CONFIG_NODE, &vtysh_route_map_cmd);
4457 install_element(RMAP_NODE, &vtysh_exit_rmap_cmd);
4458 install_element(RMAP_NODE, &vtysh_quit_rmap_cmd);
4459 install_element(RMAP_NODE, &vtysh_end_all_cmd);
4460
4461 install_node(&vty_node);
4462 install_element(CONFIG_NODE, &vtysh_line_vty_cmd);
4463 install_element(VTY_NODE, &vtysh_exit_line_vty_cmd);
4464 install_element(VTY_NODE, &vtysh_quit_line_vty_cmd);
4465 install_element(VTY_NODE, &vtysh_end_all_cmd);
4466
4467
4468 struct cmd_node *node;
4469 for (unsigned int i = 0; i < vector_active(cmdvec); i++) {
4470 node = vector_slot(cmdvec, i);
4471 if (!node || node->node == VIEW_NODE)
4472 continue;
4473 vtysh_install_default(node->node);
4474 }
4475
4476 /* vtysh */
4477
4478 install_element(VIEW_NODE, &vtysh_enable_cmd);
4479 install_element(ENABLE_NODE, &vtysh_config_terminal_cmd);
4480 install_element(ENABLE_NODE, &vtysh_disable_cmd);
4481
4482 /* "exit" command. */
4483 install_element(VIEW_NODE, &vtysh_exit_all_cmd);
4484 install_element(CONFIG_NODE, &vtysh_exit_all_cmd);
4485 install_element(VIEW_NODE, &vtysh_quit_all_cmd);
4486 install_element(CONFIG_NODE, &vtysh_quit_all_cmd);
4487
4488 /* "end" command. */
4489 install_element(CONFIG_NODE, &vtysh_end_all_cmd);
4490 install_element(ENABLE_NODE, &vtysh_end_all_cmd);
4491
4492 /* SRv6 Data-plane */
4493 install_node(&srv6_node);
4494 install_element(SEGMENT_ROUTING_NODE, &srv6_cmd);
4495 install_element(SRV6_NODE, &srv6_locators_cmd);
4496 install_element(SRV6_NODE, &exit_srv6_config_cmd);
4497 install_element(SRV6_NODE, &vtysh_end_all_cmd);
4498
4499 install_node(&srv6_locs_node);
4500 install_element(SRV6_LOCS_NODE, &srv6_locator_cmd);
4501 install_element(SRV6_LOCS_NODE, &exit_srv6_locs_config_cmd);
4502 install_element(SRV6_LOCS_NODE, &vtysh_end_all_cmd);
4503
4504 install_node(&srv6_loc_node);
4505 install_element(SRV6_LOC_NODE, &exit_srv6_loc_config_cmd);
4506 install_element(SRV6_LOC_NODE, &vtysh_end_all_cmd);
4507
4508 install_element(ENABLE_NODE, &vtysh_show_running_config_cmd);
4509 install_element(ENABLE_NODE, &vtysh_copy_running_config_cmd);
4510 install_element(ENABLE_NODE, &vtysh_copy_to_running_cmd);
4511
4512 /* "write terminal" command. */
4513 install_element(ENABLE_NODE, &vtysh_write_terminal_cmd);
4514
4515 install_element(CONFIG_NODE, &vtysh_integrated_config_cmd);
4516 install_element(CONFIG_NODE, &no_vtysh_integrated_config_cmd);
4517
4518 /* "write memory" command. */
4519 install_element(ENABLE_NODE, &vtysh_write_memory_cmd);
4520
4521 install_element(CONFIG_NODE, &vtysh_terminal_paginate_cmd);
4522 install_element(VIEW_NODE, &vtysh_terminal_paginate_cmd);
4523 install_element(VIEW_NODE, &vtysh_terminal_length_cmd);
4524 install_element(VIEW_NODE, &vtysh_terminal_no_length_cmd);
4525 install_element(VIEW_NODE, &vtysh_show_daemons_cmd);
4526
4527 install_element(VIEW_NODE, &vtysh_ping_cmd);
4528 install_element(VIEW_NODE, &vtysh_ping_ip_cmd);
4529 install_element(VIEW_NODE, &vtysh_traceroute_cmd);
4530 install_element(VIEW_NODE, &vtysh_traceroute_ip_cmd);
4531 install_element(VIEW_NODE, &vtysh_mtrace_cmd);
4532 install_element(VIEW_NODE, &vtysh_ping6_cmd);
4533 install_element(VIEW_NODE, &vtysh_traceroute6_cmd);
4534 #if defined(HAVE_SHELL_ACCESS)
4535 install_element(VIEW_NODE, &vtysh_telnet_cmd);
4536 install_element(VIEW_NODE, &vtysh_telnet_port_cmd);
4537 install_element(VIEW_NODE, &vtysh_ssh_cmd);
4538 #endif
4539 #if defined(HAVE_SHELL_ACCESS)
4540 install_element(ENABLE_NODE, &vtysh_start_shell_cmd);
4541 install_element(ENABLE_NODE, &vtysh_start_bash_cmd);
4542 install_element(ENABLE_NODE, &vtysh_start_zsh_cmd);
4543 #endif
4544
4545 /* debugging */
4546 install_element(VIEW_NODE, &vtysh_show_error_code_cmd);
4547 install_element(ENABLE_NODE, &vtysh_show_debugging_cmd);
4548 install_element(ENABLE_NODE, &vtysh_show_debugging_hashtable_cmd);
4549 install_element(ENABLE_NODE, &vtysh_debug_all_cmd);
4550 install_element(CONFIG_NODE, &vtysh_debug_all_cmd);
4551 install_element(ENABLE_NODE, &vtysh_debug_memstats_cmd);
4552 install_element(CONFIG_NODE, &vtysh_debug_memstats_cmd);
4553
4554 /* northbound */
4555 install_element(ENABLE_NODE, &show_config_running_cmd);
4556 install_element(ENABLE_NODE, &show_yang_operational_data_cmd);
4557 install_element(ENABLE_NODE, &show_yang_module_cmd);
4558 install_element(ENABLE_NODE, &show_yang_module_detail_cmd);
4559 install_element(ENABLE_NODE, &debug_nb_cmd);
4560 install_element(CONFIG_NODE, &debug_nb_cmd);
4561
4562 /* misc lib show commands */
4563 install_element(VIEW_NODE, &vtysh_show_history_cmd);
4564 install_element(VIEW_NODE, &vtysh_show_memory_cmd);
4565 install_element(VIEW_NODE, &vtysh_show_modules_cmd);
4566 install_element(VIEW_NODE, &vtysh_show_work_queues_cmd);
4567 install_element(VIEW_NODE, &vtysh_show_work_queues_daemon_cmd);
4568 install_element(VIEW_NODE, &vtysh_show_thread_cmd);
4569 install_element(VIEW_NODE, &vtysh_show_poll_cmd);
4570
4571 /* Logging */
4572 install_element(VIEW_NODE, &vtysh_show_logging_cmd);
4573
4574 install_element(CONFIG_NODE, &vtysh_service_password_encrypt_cmd);
4575 install_element(CONFIG_NODE, &no_vtysh_service_password_encrypt_cmd);
4576
4577 install_element(CONFIG_NODE, &vtysh_password_cmd);
4578 install_element(CONFIG_NODE, &no_vtysh_password_cmd);
4579 install_element(CONFIG_NODE, &vtysh_enable_password_cmd);
4580 install_element(CONFIG_NODE, &no_vtysh_enable_password_cmd);
4581 }