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