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