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