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