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