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