]> git.proxmox.com Git - mirror_frr.git/blob - vtysh/vtysh.c
vtysh: vtysh-warnings.patch
[mirror_frr.git] / vtysh / vtysh.c
1 /* Virtual terminal interface shell.
2 * Copyright (C) 2000 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23
24 #include <sys/un.h>
25 #include <setjmp.h>
26 #include <sys/wait.h>
27 #include <sys/resource.h>
28 #include <sys/stat.h>
29
30 #include <readline/readline.h>
31 #include <readline/history.h>
32
33 #include <dirent.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #include "command.h"
38 #include "memory.h"
39 #include "vtysh/vtysh.h"
40 #include "log.h"
41 #include "bgpd/bgp_vty.h"
42
43 /* Struct VTY. */
44 struct vty *vty;
45
46 /* VTY shell pager name. */
47 char *vtysh_pager_name = NULL;
48
49 /* VTY shell client structure. */
50 struct vtysh_client
51 {
52 int fd;
53 const char *name;
54 int flag;
55 const char *path;
56 struct vtysh_client *next;
57 };
58
59 struct vtysh_client vtysh_client[] =
60 {
61 { .fd = -1, .name = "zebra", .flag = VTYSH_ZEBRA, .path = ZEBRA_VTYSH_PATH, .next = NULL},
62 { .fd = -1, .name = "ripd", .flag = VTYSH_RIPD, .path = RIP_VTYSH_PATH, .next = NULL},
63 { .fd = -1, .name = "ripngd", .flag = VTYSH_RIPNGD, .path = RIPNG_VTYSH_PATH, .next = NULL},
64 { .fd = -1, .name = "ospfd", .flag = VTYSH_OSPFD, .path = OSPF_VTYSH_PATH, .next = NULL},
65 { .fd = -1, .name = "ospf6d", .flag = VTYSH_OSPF6D, .path = OSPF6_VTYSH_PATH, .next = NULL},
66 { .fd = -1, .name = "bgpd", .flag = VTYSH_BGPD, .path = BGP_VTYSH_PATH, .next = NULL},
67 { .fd = -1, .name = "isisd", .flag = VTYSH_ISISD, .path = ISIS_VTYSH_PATH, .next = NULL},
68 { .fd = -1, .name = "babeld", .flag = VTYSH_BABELD, .path = BABEL_VTYSH_PATH, .next = NULL},
69 };
70
71 /*
72 * Compiler is warning about prototypes not being declared.
73 * The DEFUNSH and DEFUN macro's are messing with the
74 * compiler I believe. This is just to make it happy.
75 */
76 int vtysh_end(void);
77 int vtysh_rl_describe(void);
78 void vtysh_exit_ripd_only(void);
79 int vtysh_connect_all_instances(struct vtysh_client *);
80
81
82 /* We need direct access to ripd to implement vtysh_exit_ripd_only. */
83 static struct vtysh_client *ripd_client = NULL;
84
85
86 /* Using integrated config from Quagga.conf. Default is no. */
87 int vtysh_writeconfig_integrated = 0;
88
89 extern char config_default[];
90
91 static void
92 vclient_close (struct vtysh_client *vclient)
93 {
94 if (vclient->fd >= 0)
95 {
96 fprintf(stderr,
97 "Warning: closing connection to %s because of an I/O error!\n",
98 vclient->name);
99 close (vclient->fd);
100 vclient->fd = -1;
101 }
102 }
103
104 /* Following filled with debug code to trace a problematic condition
105 * under load - it SHOULD handle it. */
106 #define ERR_WHERE_STRING "vtysh(): vtysh_client_config(): "
107 static int
108 vtysh_client_config_one (struct vtysh_client *vclient, char *line)
109 {
110 int ret;
111 char *buf;
112 size_t bufsz;
113 char *pbuf;
114 size_t left;
115 char *eoln;
116 int nbytes;
117 int i;
118 int readln;
119
120 if (vclient->fd < 0)
121 return CMD_SUCCESS;
122
123 ret = write (vclient->fd, line, strlen (line) + 1);
124 if (ret <= 0)
125 {
126 vclient_close (vclient);
127 return CMD_SUCCESS;
128 }
129
130 /* Allow enough room for buffer to read more than a few pages from socket. */
131 bufsz = 5 * getpagesize() + 1;
132 buf = XMALLOC(MTYPE_TMP, bufsz);
133 memset(buf, 0, bufsz);
134 pbuf = buf;
135
136 while (1)
137 {
138 if (pbuf >= ((buf + bufsz) -1))
139 {
140 fprintf (stderr, ERR_WHERE_STRING \
141 "warning - pbuf beyond buffer end.\n");
142 return CMD_WARNING;
143 }
144
145 readln = (buf + bufsz) - pbuf - 1;
146 nbytes = read (vclient->fd, pbuf, readln);
147
148 if (nbytes <= 0)
149 {
150
151 if (errno == EINTR)
152 continue;
153
154 fprintf(stderr, ERR_WHERE_STRING "(%u)", errno);
155 perror("");
156
157 if (errno == EAGAIN || errno == EIO)
158 continue;
159
160 vclient_close (vclient);
161 XFREE(MTYPE_TMP, buf);
162 return CMD_SUCCESS;
163 }
164
165 pbuf[nbytes] = '\0';
166
167 if (nbytes >= 4)
168 {
169 i = nbytes - 4;
170 if (pbuf[i] == '\0' && pbuf[i + 1] == '\0' && pbuf[i + 2] == '\0')
171 {
172 ret = pbuf[i + 3];
173 break;
174 }
175 }
176 pbuf += nbytes;
177
178 /* See if a line exists in buffer, if so parse and consume it, and
179 * reset read position. */
180 if ((eoln = strrchr(buf, '\n')) == NULL)
181 continue;
182
183 if (eoln >= ((buf + bufsz) - 1))
184 {
185 fprintf (stderr, ERR_WHERE_STRING \
186 "warning - eoln beyond buffer end.\n");
187 }
188 vtysh_config_parse(buf);
189
190 eoln++;
191 left = (size_t)(buf + bufsz - eoln);
192 memmove(buf, eoln, left);
193 buf[bufsz-1] = '\0';
194 pbuf = buf + strlen(buf);
195 }
196
197 /* Parse anything left in the buffer. */
198
199 vtysh_config_parse (buf);
200
201 XFREE(MTYPE_TMP, buf);
202 return ret;
203 }
204
205 static void
206 vtysh_client_config (struct vtysh_client *head_client, char *line)
207 {
208 struct vtysh_client *client;
209 int rc;
210
211 rc = vtysh_client_config_one(head_client, line);
212 if (rc != CMD_SUCCESS)
213 return;
214
215 client = head_client->next;
216 while (client)
217 {
218 rc = vtysh_client_config_one(client, line);
219 if (rc != CMD_SUCCESS)
220 return;
221 client = client->next;
222 }
223 return;
224 }
225
226 static int
227 vtysh_client_execute_one (struct vtysh_client *vclient, const char *line, FILE *fp)
228 {
229 int ret;
230 char buf[1001];
231 int nbytes;
232 int i;
233 int numnulls = 0;
234
235 if (vclient->fd < 0)
236 return CMD_SUCCESS;
237
238 ret = write (vclient->fd, line, strlen (line) + 1);
239 if (ret <= 0)
240 {
241 vclient_close (vclient);
242 return CMD_SUCCESS;
243 }
244
245 while (1)
246 {
247 nbytes = read (vclient->fd, buf, sizeof(buf)-1);
248
249 if (nbytes <= 0 && errno != EINTR)
250 {
251 vclient_close (vclient);
252 return CMD_SUCCESS;
253 }
254
255 if (nbytes > 0)
256 {
257 if ((numnulls == 3) && (nbytes == 1))
258 return buf[0];
259
260 buf[nbytes] = '\0';
261 fputs (buf, fp);
262 fflush (fp);
263
264 /* check for trailling \0\0\0<ret code>,
265 * even if split across reads
266 * (see lib/vty.c::vtysh_read)
267 */
268 if (nbytes >= 4)
269 {
270 i = nbytes-4;
271 numnulls = 0;
272 }
273 else
274 i = 0;
275
276 while (i < nbytes && numnulls < 3)
277 {
278 if (buf[i++] == '\0')
279 numnulls++;
280 else
281 numnulls = 0;
282 }
283
284 /* got 3 or more trailing NULs? */
285 if ((numnulls >= 3) && (i < nbytes))
286 return (buf[nbytes-1]);
287 }
288 }
289 }
290
291 static int
292 vtysh_client_execute (struct vtysh_client *head_client, const char *line, FILE *fp)
293 {
294 struct vtysh_client *client;
295 int rc;
296
297 rc = vtysh_client_execute_one(head_client, line, fp);
298 if (rc != CMD_SUCCESS)
299 return rc;
300
301 client = head_client->next;
302 while (client)
303 {
304 rc = vtysh_client_execute_one(client, line, fp);
305 if (rc != CMD_SUCCESS)
306 return rc;
307 client = client->next;
308 }
309 return CMD_SUCCESS;
310 }
311
312 void
313 vtysh_exit_ripd_only (void)
314 {
315 if (ripd_client)
316 vtysh_client_execute (ripd_client, "exit", stdout);
317 }
318
319
320 void
321 vtysh_pager_init (void)
322 {
323 char *pager_defined;
324
325 pager_defined = getenv ("VTYSH_PAGER");
326
327 if (pager_defined)
328 vtysh_pager_name = strdup (pager_defined);
329 else
330 vtysh_pager_name = strdup ("more");
331 }
332
333 /* Command execution over the vty interface. */
334 static int
335 vtysh_execute_func (const char *line, int pager)
336 {
337 int ret, cmd_stat;
338 u_int i;
339 vector vline;
340 struct cmd_element *cmd;
341 FILE *fp = NULL;
342 int closepager = 0;
343 int tried = 0;
344 int saved_ret, saved_node;
345
346 /* Split readline string up into the vector. */
347 vline = cmd_make_strvec (line);
348
349 if (vline == NULL)
350 return CMD_SUCCESS;
351
352 saved_ret = ret = cmd_execute_command (vline, vty, &cmd, 1);
353 saved_node = vty->node;
354
355 /* If command doesn't succeeded in current node, try to walk up in node tree.
356 * Changing vty->node is enough to try it just out without actual walkup in
357 * the vtysh. */
358 while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON && ret != CMD_WARNING
359 && vty->node > CONFIG_NODE)
360 {
361 vty->node = node_parent(vty->node);
362 ret = cmd_execute_command (vline, vty, &cmd, 1);
363 tried++;
364 }
365
366 vty->node = saved_node;
367
368 /* If command succeeded in any other node than current (tried > 0) we have
369 * to move into node in the vtysh where it succeeded. */
370 if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON || ret == CMD_WARNING)
371 {
372 if ((saved_node == BGP_VPNV4_NODE || saved_node == BGP_IPV4_NODE
373 || saved_node == BGP_IPV6_NODE || saved_node == BGP_IPV4M_NODE
374 || saved_node == BGP_IPV6M_NODE)
375 && (tried == 1))
376 {
377 vtysh_execute("exit-address-family");
378 }
379 else if ((saved_node == KEYCHAIN_KEY_NODE) && (tried == 1))
380 {
381 vtysh_execute("exit");
382 }
383 else if (tried)
384 {
385 vtysh_execute ("end");
386 vtysh_execute ("configure terminal");
387 }
388 }
389 /* If command didn't succeed in any node, continue with return value from
390 * first try. */
391 else if (tried)
392 {
393 ret = saved_ret;
394 }
395
396 cmd_free_strvec (vline);
397
398 cmd_stat = ret;
399 switch (ret)
400 {
401 case CMD_WARNING:
402 if (vty->type == VTY_FILE)
403 fprintf (stdout,"Warning...\n");
404 break;
405 case CMD_ERR_AMBIGUOUS:
406 fprintf (stdout,"%% Ambiguous command.\n");
407 break;
408 case CMD_ERR_NO_MATCH:
409 fprintf (stdout,"%% Unknown command.\n");
410 break;
411 case CMD_ERR_INCOMPLETE:
412 fprintf (stdout,"%% Command incomplete.\n");
413 break;
414 case CMD_SUCCESS_DAEMON:
415 {
416 /* FIXME: Don't open pager for exit commands. popen() causes problems
417 * if exited from vtysh at all. This hack shouldn't cause any problem
418 * but is really ugly. */
419 if (pager && vtysh_pager_name && (strncmp(line, "exit", 4) != 0))
420 {
421 fp = popen (vtysh_pager_name, "w");
422 if (fp == NULL)
423 {
424 perror ("popen failed for pager");
425 fp = stdout;
426 }
427 else
428 closepager=1;
429 }
430 else
431 fp = stdout;
432
433 if (! strcmp(cmd->string,"configure terminal"))
434 {
435 for (i = 0; i < array_size(vtysh_client); i++)
436 {
437 cmd_stat = vtysh_client_execute(&vtysh_client[i], line, fp);
438 if (cmd_stat == CMD_WARNING)
439 break;
440 }
441
442 if (cmd_stat)
443 {
444 line = "end";
445 vline = cmd_make_strvec (line);
446
447 if (vline == NULL)
448 {
449 if (pager && vtysh_pager_name && fp && closepager)
450 {
451 if (pclose (fp) == -1)
452 {
453 perror ("pclose failed for pager");
454 }
455 fp = NULL;
456 }
457 return CMD_SUCCESS;
458 }
459
460 ret = cmd_execute_command (vline, vty, &cmd, 1);
461 cmd_free_strvec (vline);
462 if (ret != CMD_SUCCESS_DAEMON)
463 break;
464 }
465 else
466 if (cmd->func)
467 {
468 (*cmd->func) (cmd, vty, 0, NULL);
469 break;
470 }
471 }
472
473 cmd_stat = CMD_SUCCESS;
474 for (i = 0; i < array_size(vtysh_client); i++)
475 {
476 if (cmd->daemon & vtysh_client[i].flag)
477 {
478 cmd_stat = vtysh_client_execute(&vtysh_client[i], line, fp);
479 if (cmd_stat != CMD_SUCCESS)
480 break;
481 }
482 }
483 if (cmd_stat != CMD_SUCCESS)
484 break;
485
486 if (cmd->func)
487 (*cmd->func) (cmd, vty, 0, NULL);
488 }
489 }
490 if (pager && vtysh_pager_name && fp && closepager)
491 {
492 if (pclose (fp) == -1)
493 {
494 perror ("pclose failed for pager");
495 }
496 fp = NULL;
497 }
498 return cmd_stat;
499 }
500
501 int
502 vtysh_execute_no_pager (const char *line)
503 {
504 return vtysh_execute_func (line, 0);
505 }
506
507 int
508 vtysh_execute (const char *line)
509 {
510 return vtysh_execute_func (line, 1);
511 }
512
513 int
514 vtysh_mark_file (const char *filename)
515 {
516 struct vty *vty;
517 FILE *confp = NULL;
518 int ret;
519 vector vline;
520 int tried = 0;
521 struct cmd_element *cmd;
522 int saved_ret, prev_node;
523 int lineno = 0;
524
525 if (strncmp("-", filename, 1) == 0)
526 confp = stdin;
527 else
528 confp = fopen (filename, "r");
529
530 if (confp == NULL)
531 return (1);
532
533 vty = vty_new ();
534 vty->fd = 0; /* stdout */
535 vty->type = VTY_TERM;
536 vty->node = CONFIG_NODE;
537
538 vtysh_execute_no_pager ("enable");
539 vtysh_execute_no_pager ("configure terminal");
540
541 while (fgets (vty->buf, VTY_BUFSIZ, confp))
542 {
543 lineno++;
544 tried = 0;
545
546 if (vty->buf[0] == '!' || vty->buf[1] == '#')
547 {
548 fprintf(stdout, "%s", vty->buf);
549 continue;
550 }
551
552 /* Split readline string up into the vector. */
553 vline = cmd_make_strvec (vty->buf);
554
555 if (vline == NULL)
556 {
557 fprintf(stdout, "%s", vty->buf);
558 continue;
559 }
560
561 prev_node = vty->node;
562 saved_ret = ret = cmd_execute_command_strict (vline, vty, &cmd);
563
564 /* If command doesn't succeeded in current node, try to walk up in node tree.
565 * Changing vty->node is enough to try it just out without actual walkup in
566 * the vtysh. */
567 while (ret != CMD_SUCCESS && ret != CMD_SUCCESS_DAEMON && ret != CMD_WARNING
568 && vty->node > CONFIG_NODE)
569 {
570 vty->node = node_parent(vty->node);
571 ret = cmd_execute_command_strict (vline, vty, &cmd);
572 tried++;
573 }
574
575 /* If command succeeded in any other node than current (tried > 0) we have
576 * to move into node in the vtysh where it succeeded. */
577 if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON || ret == CMD_WARNING)
578 {
579 if ((prev_node == BGP_VPNV4_NODE || prev_node == BGP_IPV4_NODE
580 || prev_node == BGP_IPV6_NODE || prev_node == BGP_IPV4M_NODE
581 || prev_node == BGP_IPV6M_NODE)
582 && (tried == 1))
583 {
584 fprintf(stdout, "exit-address-family\n");
585 }
586 else if ((prev_node == KEYCHAIN_KEY_NODE) && (tried == 1))
587 {
588 fprintf(stdout, "exit\n");
589 }
590 else if (tried)
591 {
592 fprintf(stdout, "end\n");
593 }
594 }
595 /* If command didn't succeed in any node, continue with return value from
596 * first try. */
597 else if (tried)
598 {
599 ret = saved_ret;
600 vty->node = prev_node;
601 }
602
603 cmd_free_strvec (vline);
604 switch (ret)
605 {
606 case CMD_WARNING:
607 if (vty->type == VTY_FILE)
608 fprintf (stderr,"line %d: Warning...: %s\n", lineno, vty->buf);
609 fclose(confp);
610 vty_close(vty);
611 return (1);
612 case CMD_ERR_AMBIGUOUS:
613 fprintf (stderr,"line %d: %% Ambiguous command: %s\n", lineno, vty->buf);
614 fclose(confp);
615 vty_close(vty);
616 return(1);
617 case CMD_ERR_NO_MATCH:
618 fprintf (stderr,"line %d: %% Unknown command: %s\n", lineno, vty->buf);
619 fclose(confp);
620 vty_close(vty);
621 return(1);
622 case CMD_ERR_INCOMPLETE:
623 fprintf (stderr,"line %d: %% Command incomplete: %s\n", lineno, vty->buf);
624 fclose(confp);
625 vty_close(vty);
626 return(1);
627 case CMD_SUCCESS:
628 fprintf(stdout, "%s", vty->buf);
629 break;
630 case CMD_SUCCESS_DAEMON:
631 {
632 u_int i;
633 int cmd_stat = CMD_SUCCESS;
634
635 fprintf(stdout, "%s", vty->buf);
636 for (i = 0; i < array_size(vtysh_client); i++)
637 {
638 if (cmd->daemon & vtysh_client[i].flag)
639 {
640 cmd_stat = vtysh_client_execute (&vtysh_client[i],
641 vty->buf, stdout);
642 if (cmd_stat != CMD_SUCCESS)
643 break;
644 }
645 }
646 if (cmd_stat != CMD_SUCCESS)
647 break;
648
649 if (cmd->func)
650 (*cmd->func) (cmd, vty, 0, NULL);
651 }
652 }
653 }
654 /* This is the end */
655 fprintf(stdout, "end\n");
656 vty_close(vty);
657
658 if (confp != stdin)
659 fclose(confp);
660
661 return (0);
662 }
663
664 /* Configration make from file. */
665 int
666 vtysh_config_from_file (struct vty *vty, FILE *fp)
667 {
668 int ret;
669 vector vline;
670 struct cmd_element *cmd;
671 int save_node = CONFIG_NODE;
672
673 while (fgets (vty->buf, VTY_BUFSIZ, fp))
674 {
675 if (vty->buf[0] == '!' || vty->buf[1] == '#')
676 continue;
677
678 vline = cmd_make_strvec (vty->buf);
679
680 /* In case of comment line. */
681 if (vline == NULL)
682 continue;
683
684 /* Execute configuration command : this is strict match. */
685 ret = cmd_execute_command_strict (vline, vty, &cmd);
686
687 /* Try again with setting node to CONFIG_NODE. */
688 if (ret != CMD_SUCCESS
689 && ret != CMD_SUCCESS_DAEMON
690 && ret != CMD_WARNING)
691 {
692 if (vty->node == KEYCHAIN_KEY_NODE)
693 {
694 vty->node = KEYCHAIN_NODE;
695 vtysh_exit_ripd_only ();
696 ret = cmd_execute_command_strict (vline, vty, &cmd);
697
698 if (ret != CMD_SUCCESS
699 && ret != CMD_SUCCESS_DAEMON
700 && ret != CMD_WARNING)
701 {
702 vtysh_exit_ripd_only ();
703 vty->node = CONFIG_NODE;
704 ret = cmd_execute_command_strict (vline, vty, &cmd);
705 }
706 }
707 else
708 {
709 save_node = vty->node;
710 vtysh_execute ("end");
711 vtysh_execute ("configure terminal");
712 vty->node = CONFIG_NODE;
713 ret = cmd_execute_command_strict (vline, vty, &cmd);
714 if ((ret != CMD_SUCCESS) &&
715 (ret != CMD_SUCCESS_DAEMON) &&
716 (ret != CMD_WARNING))
717 vty->node = save_node;
718 }
719 }
720
721 cmd_free_strvec (vline);
722
723 switch (ret)
724 {
725 case CMD_WARNING:
726 if (vty->type == VTY_FILE)
727 fprintf (stdout,"Warning...\n");
728 break;
729 case CMD_ERR_AMBIGUOUS:
730 fprintf (stdout,"%% Ambiguous command: %s\n", vty->buf);
731 break;
732 case CMD_ERR_NO_MATCH:
733 fprintf (stdout,"%% Unknown command: %s", vty->buf);
734 break;
735 case CMD_ERR_INCOMPLETE:
736 fprintf (stdout,"%% Command incomplete: %s\n", vty->buf);
737 break;
738 case CMD_SUCCESS_DAEMON:
739 {
740 u_int i;
741 int cmd_stat = CMD_SUCCESS;
742
743 for (i = 0; i < array_size(vtysh_client); i++)
744 {
745 if (cmd->daemon & vtysh_client[i].flag)
746 {
747 cmd_stat = vtysh_client_execute (&vtysh_client[i],
748 vty->buf, stdout);
749 if (cmd_stat != CMD_SUCCESS)
750 break;
751 }
752 }
753 if (cmd_stat != CMD_SUCCESS)
754 break;
755
756 if (cmd->func)
757 (*cmd->func) (cmd, vty, 0, NULL);
758 }
759 }
760 }
761 return CMD_SUCCESS;
762 }
763
764 /* We don't care about the point of the cursor when '?' is typed. */
765 int
766 vtysh_rl_describe (void)
767 {
768 int ret;
769 unsigned int i;
770 vector vline;
771 vector describe;
772 int width;
773 struct cmd_token *token;
774
775 vline = cmd_make_strvec (rl_line_buffer);
776
777 /* In case of '> ?'. */
778 if (vline == NULL)
779 {
780 vline = vector_init (1);
781 vector_set (vline, '\0');
782 }
783 else
784 if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
785 vector_set (vline, '\0');
786
787 describe = cmd_describe_command (vline, vty, &ret);
788
789 fprintf (stdout,"\n");
790
791 /* Ambiguous and no match error. */
792 switch (ret)
793 {
794 case CMD_ERR_AMBIGUOUS:
795 cmd_free_strvec (vline);
796 fprintf (stdout,"%% Ambiguous command.\n");
797 rl_on_new_line ();
798 return 0;
799 break;
800 case CMD_ERR_NO_MATCH:
801 cmd_free_strvec (vline);
802 fprintf (stdout,"%% There is no matched command.\n");
803 rl_on_new_line ();
804 return 0;
805 break;
806 }
807
808 /* Get width of command string. */
809 width = 0;
810 for (i = 0; i < vector_active (describe); i++)
811 if ((token = vector_slot (describe, i)) != NULL)
812 {
813 int len;
814
815 if (token->cmd[0] == '\0')
816 continue;
817
818 len = strlen (token->cmd);
819 if (token->cmd[0] == '.')
820 len--;
821
822 if (width < len)
823 width = len;
824 }
825
826 for (i = 0; i < vector_active (describe); i++)
827 if ((token = vector_slot (describe, i)) != NULL)
828 {
829 if (token->cmd[0] == '\0')
830 continue;
831
832 if (! token->desc)
833 fprintf (stdout," %-s\n",
834 token->cmd[0] == '.' ? token->cmd + 1 : token->cmd);
835 else
836 fprintf (stdout," %-*s %s\n",
837 width,
838 token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
839 token->desc);
840 }
841
842 cmd_free_strvec (vline);
843 vector_free (describe);
844
845 rl_on_new_line();
846
847 return 0;
848 }
849
850 /* Result of cmd_complete_command() call will be stored here
851 * and used in new_completion() in order to put the space in
852 * correct places only. */
853 int complete_status;
854
855 static char *
856 command_generator (const char *text, int state)
857 {
858 vector vline;
859 static char **matched = NULL;
860 static int index = 0;
861
862 /* First call. */
863 if (! state)
864 {
865 index = 0;
866
867 if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
868 return NULL;
869
870 vline = cmd_make_strvec (rl_line_buffer);
871 if (vline == NULL)
872 return NULL;
873
874 if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
875 vector_set (vline, '\0');
876
877 matched = cmd_complete_command (vline, vty, &complete_status);
878 }
879
880 if (matched && matched[index])
881 return matched[index++];
882
883 return NULL;
884 }
885
886 static char **
887 new_completion (char *text, int start, int end)
888 {
889 char **matches;
890
891 matches = rl_completion_matches (text, command_generator);
892
893 if (matches)
894 {
895 rl_point = rl_end;
896 if (complete_status != CMD_COMPLETE_FULL_MATCH)
897 /* only append a space on full match */
898 rl_completion_append_character = '\0';
899 }
900
901 return matches;
902 }
903
904 #if 0
905 /* This function is not actually being used. */
906 static char **
907 vtysh_completion (char *text, int start, int end)
908 {
909 int ret;
910 vector vline;
911 char **matched = NULL;
912
913 if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
914 return NULL;
915
916 vline = cmd_make_strvec (rl_line_buffer);
917 if (vline == NULL)
918 return NULL;
919
920 /* In case of 'help \t'. */
921 if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
922 vector_set (vline, '\0');
923
924 matched = cmd_complete_command (vline, vty, &ret);
925
926 cmd_free_strvec (vline);
927
928 return (char **) matched;
929 }
930 #endif
931
932 /* Vty node structures. */
933 static struct cmd_node bgp_node =
934 {
935 BGP_NODE,
936 "%s(config-router)# ",
937 };
938
939 static struct cmd_node rip_node =
940 {
941 RIP_NODE,
942 "%s(config-router)# ",
943 };
944
945 static struct cmd_node isis_node =
946 {
947 ISIS_NODE,
948 "%s(config-router)# ",
949 };
950
951 static struct cmd_node interface_node =
952 {
953 INTERFACE_NODE,
954 "%s(config-if)# ",
955 };
956
957 static struct cmd_node rmap_node =
958 {
959 RMAP_NODE,
960 "%s(config-route-map)# "
961 };
962
963 static struct cmd_node zebra_node =
964 {
965 ZEBRA_NODE,
966 "%s(config-router)# "
967 };
968
969 static struct cmd_node bgp_vpnv4_node =
970 {
971 BGP_VPNV4_NODE,
972 "%s(config-router-af)# "
973 };
974
975 static struct cmd_node bgp_ipv4_node =
976 {
977 BGP_IPV4_NODE,
978 "%s(config-router-af)# "
979 };
980
981 static struct cmd_node bgp_ipv4m_node =
982 {
983 BGP_IPV4M_NODE,
984 "%s(config-router-af)# "
985 };
986
987 static struct cmd_node bgp_ipv6_node =
988 {
989 BGP_IPV6_NODE,
990 "%s(config-router-af)# "
991 };
992
993 static struct cmd_node bgp_ipv6m_node =
994 {
995 BGP_IPV6M_NODE,
996 "%s(config-router-af)# "
997 };
998
999 static struct cmd_node ospf_node =
1000 {
1001 OSPF_NODE,
1002 "%s(config-router)# "
1003 };
1004
1005 static struct cmd_node ripng_node =
1006 {
1007 RIPNG_NODE,
1008 "%s(config-router)# "
1009 };
1010
1011 static struct cmd_node ospf6_node =
1012 {
1013 OSPF6_NODE,
1014 "%s(config-ospf6)# "
1015 };
1016
1017 static struct cmd_node babel_node =
1018 {
1019 BABEL_NODE,
1020 "%s(config-babel)# "
1021 };
1022
1023 static struct cmd_node keychain_node =
1024 {
1025 KEYCHAIN_NODE,
1026 "%s(config-keychain)# "
1027 };
1028
1029 static struct cmd_node keychain_key_node =
1030 {
1031 KEYCHAIN_KEY_NODE,
1032 "%s(config-keychain-key)# "
1033 };
1034
1035 /* Defined in lib/vty.c */
1036 extern struct cmd_node vty_node;
1037
1038 /* When '^Z' is received from vty, move down to the enable mode. */
1039 int
1040 vtysh_end (void)
1041 {
1042 switch (vty->node)
1043 {
1044 case VIEW_NODE:
1045 case ENABLE_NODE:
1046 /* Nothing to do. */
1047 break;
1048 default:
1049 vty->node = ENABLE_NODE;
1050 break;
1051 }
1052 return CMD_SUCCESS;
1053 }
1054
1055 DEFUNSH (VTYSH_ALL,
1056 vtysh_end_all,
1057 vtysh_end_all_cmd,
1058 "end",
1059 "End current mode and change to enable mode\n")
1060 {
1061 return vtysh_end ();
1062 }
1063
1064 DEFUNSH (VTYSH_BGPD,
1065 router_bgp,
1066 router_bgp_cmd,
1067 "router bgp " CMD_AS_RANGE,
1068 ROUTER_STR
1069 BGP_STR
1070 AS_STR)
1071 {
1072 vty->node = BGP_NODE;
1073 return CMD_SUCCESS;
1074 }
1075
1076 ALIAS_SH (VTYSH_BGPD,
1077 router_bgp,
1078 router_bgp_view_cmd,
1079 "router bgp " CMD_AS_RANGE " view WORD",
1080 ROUTER_STR
1081 BGP_STR
1082 AS_STR
1083 "BGP view\n"
1084 "view name\n")
1085
1086 DEFUNSH (VTYSH_BGPD,
1087 address_family_vpnv4,
1088 address_family_vpnv4_cmd,
1089 "address-family vpnv4",
1090 "Enter Address Family command mode\n"
1091 "Address family\n")
1092 {
1093 vty->node = BGP_VPNV4_NODE;
1094 return CMD_SUCCESS;
1095 }
1096
1097 DEFUNSH (VTYSH_BGPD,
1098 address_family_vpnv4_unicast,
1099 address_family_vpnv4_unicast_cmd,
1100 "address-family vpnv4 unicast",
1101 "Enter Address Family command mode\n"
1102 "Address family\n"
1103 "Address Family Modifier\n")
1104 {
1105 vty->node = BGP_VPNV4_NODE;
1106 return CMD_SUCCESS;
1107 }
1108
1109 DEFUNSH (VTYSH_BGPD,
1110 address_family_ipv4_unicast,
1111 address_family_ipv4_unicast_cmd,
1112 "address-family ipv4 unicast",
1113 "Enter Address Family command mode\n"
1114 "Address family\n"
1115 "Address Family Modifier\n")
1116 {
1117 vty->node = BGP_IPV4_NODE;
1118 return CMD_SUCCESS;
1119 }
1120
1121 DEFUNSH (VTYSH_BGPD,
1122 address_family_ipv4_multicast,
1123 address_family_ipv4_multicast_cmd,
1124 "address-family ipv4 multicast",
1125 "Enter Address Family command mode\n"
1126 "Address family\n"
1127 "Address Family Modifier\n")
1128 {
1129 vty->node = BGP_IPV4M_NODE;
1130 return CMD_SUCCESS;
1131 }
1132
1133 DEFUNSH (VTYSH_BGPD,
1134 address_family_ipv6,
1135 address_family_ipv6_cmd,
1136 "address-family ipv6",
1137 "Enter Address Family command mode\n"
1138 "Address family\n")
1139 {
1140 vty->node = BGP_IPV6_NODE;
1141 return CMD_SUCCESS;
1142 }
1143
1144 DEFUNSH (VTYSH_BGPD,
1145 address_family_ipv6_unicast,
1146 address_family_ipv6_unicast_cmd,
1147 "address-family ipv6 unicast",
1148 "Enter Address Family command mode\n"
1149 "Address family\n"
1150 "Address Family Modifier\n")
1151 {
1152 vty->node = BGP_IPV6_NODE;
1153 return CMD_SUCCESS;
1154 }
1155
1156 DEFUNSH (VTYSH_BGPD,
1157 address_family_ipv6_multicast,
1158 address_family_ipv6_multicast_cmd,
1159 "address-family ipv6 multicast",
1160 "Enter Address Family command mode\n"
1161 "Address family\n"
1162 "Address Family Modifier\n")
1163 {
1164 vty->node = BGP_IPV6M_NODE;
1165 return CMD_SUCCESS;
1166 }
1167
1168 DEFUNSH (VTYSH_RIPD,
1169 key_chain,
1170 key_chain_cmd,
1171 "key chain WORD",
1172 "Authentication key management\n"
1173 "Key-chain management\n"
1174 "Key-chain name\n")
1175 {
1176 vty->node = KEYCHAIN_NODE;
1177 return CMD_SUCCESS;
1178 }
1179
1180 DEFUNSH (VTYSH_RIPD,
1181 key,
1182 key_cmd,
1183 "key <0-2147483647>",
1184 "Configure a key\n"
1185 "Key identifier number\n")
1186 {
1187 vty->node = KEYCHAIN_KEY_NODE;
1188 return CMD_SUCCESS;
1189 }
1190
1191 DEFUNSH (VTYSH_RIPD,
1192 router_rip,
1193 router_rip_cmd,
1194 "router rip",
1195 ROUTER_STR
1196 "RIP")
1197 {
1198 vty->node = RIP_NODE;
1199 return CMD_SUCCESS;
1200 }
1201
1202 DEFUNSH (VTYSH_RIPNGD,
1203 router_ripng,
1204 router_ripng_cmd,
1205 "router ripng",
1206 ROUTER_STR
1207 "RIPng")
1208 {
1209 vty->node = RIPNG_NODE;
1210 return CMD_SUCCESS;
1211 }
1212
1213 DEFUNSH (VTYSH_OSPFD,
1214 router_ospf,
1215 router_ospf_cmd,
1216 "router ospf",
1217 "Enable a routing process\n"
1218 "Start OSPF configuration\n")
1219 {
1220 vty->node = OSPF_NODE;
1221 return CMD_SUCCESS;
1222 }
1223
1224 ALIAS_SH (VTYSH_OSPFD,
1225 router_ospf,
1226 router_ospf_instance_cmd,
1227 "router ospf <1-65535>",
1228 "Enable a routing process\n"
1229 "Start OSPF configuration\n"
1230 "Instance ID\n")
1231
1232 DEFUNSH (VTYSH_OSPF6D,
1233 router_ospf6,
1234 router_ospf6_cmd,
1235 "router ospf6",
1236 OSPF6_ROUTER_STR
1237 OSPF6_STR)
1238 {
1239 vty->node = OSPF6_NODE;
1240 return CMD_SUCCESS;
1241 }
1242
1243 DEFUNSH (VTYSH_BABELD,
1244 router_babel,
1245 router_babel_cmd,
1246 "router babel",
1247 ROUTER_STR
1248 "Babel")
1249 {
1250 vty->node = BABEL_NODE;
1251 return CMD_SUCCESS;
1252 }
1253
1254 DEFUNSH (VTYSH_ISISD,
1255 router_isis,
1256 router_isis_cmd,
1257 "router isis WORD",
1258 ROUTER_STR
1259 "ISO IS-IS\n"
1260 "ISO Routing area tag")
1261 {
1262 vty->node = ISIS_NODE;
1263 return CMD_SUCCESS;
1264 }
1265
1266 DEFUNSH (VTYSH_RMAP,
1267 route_map,
1268 route_map_cmd,
1269 "route-map WORD (deny|permit) <1-65535>",
1270 "Create route-map or enter route-map command mode\n"
1271 "Route map tag\n"
1272 "Route map denies set operations\n"
1273 "Route map permits set operations\n"
1274 "Sequence to insert to/delete from existing route-map entry\n")
1275 {
1276 vty->node = RMAP_NODE;
1277 return CMD_SUCCESS;
1278 }
1279
1280 DEFUNSH (VTYSH_ALL,
1281 vtysh_line_vty,
1282 vtysh_line_vty_cmd,
1283 "line vty",
1284 "Configure a terminal line\n"
1285 "Virtual terminal\n")
1286 {
1287 vty->node = VTY_NODE;
1288 return CMD_SUCCESS;
1289 }
1290
1291 DEFUNSH (VTYSH_ALL,
1292 vtysh_enable,
1293 vtysh_enable_cmd,
1294 "enable",
1295 "Turn on privileged mode command\n")
1296 {
1297 vty->node = ENABLE_NODE;
1298 return CMD_SUCCESS;
1299 }
1300
1301 DEFUNSH (VTYSH_ALL,
1302 vtysh_disable,
1303 vtysh_disable_cmd,
1304 "disable",
1305 "Turn off privileged mode command\n")
1306 {
1307 if (vty->node == ENABLE_NODE)
1308 vty->node = VIEW_NODE;
1309 return CMD_SUCCESS;
1310 }
1311
1312 DEFUNSH (VTYSH_ALL,
1313 vtysh_config_terminal,
1314 vtysh_config_terminal_cmd,
1315 "configure terminal",
1316 "Configuration from vty interface\n"
1317 "Configuration terminal\n")
1318 {
1319 vty->node = CONFIG_NODE;
1320 return CMD_SUCCESS;
1321 }
1322
1323 static int
1324 vtysh_exit (struct vty *vty)
1325 {
1326 switch (vty->node)
1327 {
1328 case VIEW_NODE:
1329 case ENABLE_NODE:
1330 exit (0);
1331 break;
1332 case CONFIG_NODE:
1333 vty->node = ENABLE_NODE;
1334 break;
1335 case INTERFACE_NODE:
1336 case ZEBRA_NODE:
1337 case BGP_NODE:
1338 case RIP_NODE:
1339 case RIPNG_NODE:
1340 case OSPF_NODE:
1341 case OSPF6_NODE:
1342 case BABEL_NODE:
1343 case ISIS_NODE:
1344 case MASC_NODE:
1345 case RMAP_NODE:
1346 case VTY_NODE:
1347 case KEYCHAIN_NODE:
1348 vtysh_execute("end");
1349 vtysh_execute("configure terminal");
1350 vty->node = CONFIG_NODE;
1351 break;
1352 case BGP_VPNV4_NODE:
1353 case BGP_IPV4_NODE:
1354 case BGP_IPV4M_NODE:
1355 case BGP_IPV6_NODE:
1356 case BGP_IPV6M_NODE:
1357 vty->node = BGP_NODE;
1358 break;
1359 case KEYCHAIN_KEY_NODE:
1360 vty->node = KEYCHAIN_NODE;
1361 break;
1362 default:
1363 break;
1364 }
1365 return CMD_SUCCESS;
1366 }
1367
1368 DEFUNSH (VTYSH_ALL,
1369 vtysh_exit_all,
1370 vtysh_exit_all_cmd,
1371 "exit",
1372 "Exit current mode and down to previous mode\n")
1373 {
1374 return vtysh_exit (vty);
1375 }
1376
1377 ALIAS (vtysh_exit_all,
1378 vtysh_quit_all_cmd,
1379 "quit",
1380 "Exit current mode and down to previous mode\n")
1381
1382 DEFUNSH (VTYSH_BGPD,
1383 exit_address_family,
1384 exit_address_family_cmd,
1385 "exit-address-family",
1386 "Exit from Address Family configuration mode\n")
1387 {
1388 if (vty->node == BGP_IPV4_NODE
1389 || vty->node == BGP_IPV4M_NODE
1390 || vty->node == BGP_VPNV4_NODE
1391 || vty->node == BGP_IPV6_NODE
1392 || vty->node == BGP_IPV6M_NODE)
1393 vty->node = BGP_NODE;
1394 return CMD_SUCCESS;
1395 }
1396
1397 DEFUNSH (VTYSH_ZEBRA,
1398 vtysh_exit_zebra,
1399 vtysh_exit_zebra_cmd,
1400 "exit",
1401 "Exit current mode and down to previous mode\n")
1402 {
1403 return vtysh_exit (vty);
1404 }
1405
1406 ALIAS (vtysh_exit_zebra,
1407 vtysh_quit_zebra_cmd,
1408 "quit",
1409 "Exit current mode and down to previous mode\n")
1410
1411 DEFUNSH (VTYSH_RIPD,
1412 vtysh_exit_ripd,
1413 vtysh_exit_ripd_cmd,
1414 "exit",
1415 "Exit current mode and down to previous mode\n")
1416 {
1417 return vtysh_exit (vty);
1418 }
1419
1420 ALIAS (vtysh_exit_ripd,
1421 vtysh_quit_ripd_cmd,
1422 "quit",
1423 "Exit current mode and down to previous mode\n")
1424
1425 DEFUNSH (VTYSH_RIPNGD,
1426 vtysh_exit_ripngd,
1427 vtysh_exit_ripngd_cmd,
1428 "exit",
1429 "Exit current mode and down to previous mode\n")
1430 {
1431 return vtysh_exit (vty);
1432 }
1433
1434 ALIAS (vtysh_exit_ripngd,
1435 vtysh_quit_ripngd_cmd,
1436 "quit",
1437 "Exit current mode and down to previous mode\n")
1438
1439 DEFUNSH (VTYSH_RMAP,
1440 vtysh_exit_rmap,
1441 vtysh_exit_rmap_cmd,
1442 "exit",
1443 "Exit current mode and down to previous mode\n")
1444 {
1445 return vtysh_exit (vty);
1446 }
1447
1448 ALIAS (vtysh_exit_rmap,
1449 vtysh_quit_rmap_cmd,
1450 "quit",
1451 "Exit current mode and down to previous mode\n")
1452
1453 DEFUNSH (VTYSH_BGPD,
1454 vtysh_exit_bgpd,
1455 vtysh_exit_bgpd_cmd,
1456 "exit",
1457 "Exit current mode and down to previous mode\n")
1458 {
1459 return vtysh_exit (vty);
1460 }
1461
1462 ALIAS (vtysh_exit_bgpd,
1463 vtysh_quit_bgpd_cmd,
1464 "quit",
1465 "Exit current mode and down to previous mode\n")
1466
1467 DEFUNSH (VTYSH_OSPFD,
1468 vtysh_exit_ospfd,
1469 vtysh_exit_ospfd_cmd,
1470 "exit",
1471 "Exit current mode and down to previous mode\n")
1472 {
1473 return vtysh_exit (vty);
1474 }
1475
1476 ALIAS (vtysh_exit_ospfd,
1477 vtysh_quit_ospfd_cmd,
1478 "quit",
1479 "Exit current mode and down to previous mode\n")
1480
1481 DEFUNSH (VTYSH_OSPF6D,
1482 vtysh_exit_ospf6d,
1483 vtysh_exit_ospf6d_cmd,
1484 "exit",
1485 "Exit current mode and down to previous mode\n")
1486 {
1487 return vtysh_exit (vty);
1488 }
1489
1490 ALIAS (vtysh_exit_ospf6d,
1491 vtysh_quit_ospf6d_cmd,
1492 "quit",
1493 "Exit current mode and down to previous mode\n")
1494
1495 DEFUNSH (VTYSH_ISISD,
1496 vtysh_exit_isisd,
1497 vtysh_exit_isisd_cmd,
1498 "exit",
1499 "Exit current mode and down to previous mode\n")
1500 {
1501 return vtysh_exit (vty);
1502 }
1503
1504 ALIAS (vtysh_exit_isisd,
1505 vtysh_quit_isisd_cmd,
1506 "quit",
1507 "Exit current mode and down to previous mode\n")
1508
1509 DEFUNSH (VTYSH_ALL,
1510 vtysh_exit_line_vty,
1511 vtysh_exit_line_vty_cmd,
1512 "exit",
1513 "Exit current mode and down to previous mode\n")
1514 {
1515 return vtysh_exit (vty);
1516 }
1517
1518 ALIAS (vtysh_exit_line_vty,
1519 vtysh_quit_line_vty_cmd,
1520 "quit",
1521 "Exit current mode and down to previous mode\n")
1522
1523 DEFUNSH (VTYSH_INTERFACE,
1524 vtysh_interface,
1525 vtysh_interface_cmd,
1526 "interface IFNAME",
1527 "Select an interface to configure\n"
1528 "Interface's name\n")
1529 {
1530 vty->node = INTERFACE_NODE;
1531 return CMD_SUCCESS;
1532 }
1533
1534 /* TODO Implement "no interface command in isisd. */
1535 DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D,
1536 vtysh_no_interface_cmd,
1537 "no interface IFNAME",
1538 NO_STR
1539 "Delete a pseudo interface's configuration\n"
1540 "Interface's name\n")
1541
1542 /* TODO Implement interface description commands in ripngd, ospf6d
1543 * and isisd. */
1544 DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD,
1545 interface_desc_cmd,
1546 "description .LINE",
1547 "Interface specific description\n"
1548 "Characters describing this interface\n")
1549
1550 DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD,
1551 no_interface_desc_cmd,
1552 "no description",
1553 NO_STR
1554 "Interface specific description\n")
1555
1556 DEFUNSH (VTYSH_INTERFACE,
1557 vtysh_exit_interface,
1558 vtysh_exit_interface_cmd,
1559 "exit",
1560 "Exit current mode and down to previous mode\n")
1561 {
1562 return vtysh_exit (vty);
1563 }
1564
1565 ALIAS (vtysh_exit_interface,
1566 vtysh_quit_interface_cmd,
1567 "quit",
1568 "Exit current mode and down to previous mode\n")
1569
1570 /* Memory */
1571 DEFUN (vtysh_show_memory,
1572 vtysh_show_memory_cmd,
1573 "show memory",
1574 SHOW_STR
1575 "Memory statistics\n")
1576 {
1577 unsigned int i;
1578 int ret = CMD_SUCCESS;
1579 char line[] = "show memory\n";
1580
1581 for (i = 0; i < array_size(vtysh_client); i++)
1582 if ( vtysh_client[i].fd >= 0 )
1583 {
1584 fprintf (stdout, "Memory statistics for %s:\n",
1585 vtysh_client[i].name);
1586 ret = vtysh_client_execute (&vtysh_client[i], line, stdout);
1587 fprintf (stdout,"\n");
1588 }
1589
1590 return ret;
1591 }
1592
1593 /* Logging commands. */
1594 DEFUN (vtysh_show_logging,
1595 vtysh_show_logging_cmd,
1596 "show logging",
1597 SHOW_STR
1598 "Show current logging configuration\n")
1599 {
1600 unsigned int i;
1601 int ret = CMD_SUCCESS;
1602 char line[] = "show logging\n";
1603
1604 for (i = 0; i < array_size(vtysh_client); i++)
1605 if ( vtysh_client[i].fd >= 0 )
1606 {
1607 fprintf (stdout,"Logging configuration for %s:\n",
1608 vtysh_client[i].name);
1609 ret = vtysh_client_execute (&vtysh_client[i], line, stdout);
1610 fprintf (stdout,"\n");
1611 }
1612
1613 return ret;
1614 }
1615
1616 DEFUNSH (VTYSH_ALL,
1617 vtysh_log_stdout,
1618 vtysh_log_stdout_cmd,
1619 "log stdout",
1620 "Logging control\n"
1621 "Set stdout logging level\n")
1622 {
1623 return CMD_SUCCESS;
1624 }
1625
1626 DEFUNSH (VTYSH_ALL,
1627 vtysh_log_stdout_level,
1628 vtysh_log_stdout_level_cmd,
1629 "log stdout "LOG_LEVELS,
1630 "Logging control\n"
1631 "Set stdout logging level\n"
1632 LOG_LEVEL_DESC)
1633 {
1634 return CMD_SUCCESS;
1635 }
1636
1637 DEFUNSH (VTYSH_ALL,
1638 no_vtysh_log_stdout,
1639 no_vtysh_log_stdout_cmd,
1640 "no log stdout [LEVEL]",
1641 NO_STR
1642 "Logging control\n"
1643 "Cancel logging to stdout\n"
1644 "Logging level\n")
1645 {
1646 return CMD_SUCCESS;
1647 }
1648
1649 DEFUNSH (VTYSH_ALL,
1650 vtysh_log_file,
1651 vtysh_log_file_cmd,
1652 "log file FILENAME",
1653 "Logging control\n"
1654 "Logging to file\n"
1655 "Logging filename\n")
1656 {
1657 return CMD_SUCCESS;
1658 }
1659
1660 DEFUNSH (VTYSH_ALL,
1661 vtysh_log_file_level,
1662 vtysh_log_file_level_cmd,
1663 "log file FILENAME "LOG_LEVELS,
1664 "Logging control\n"
1665 "Logging to file\n"
1666 "Logging filename\n"
1667 LOG_LEVEL_DESC)
1668 {
1669 return CMD_SUCCESS;
1670 }
1671
1672 DEFUNSH (VTYSH_ALL,
1673 no_vtysh_log_file,
1674 no_vtysh_log_file_cmd,
1675 "no log file [FILENAME]",
1676 NO_STR
1677 "Logging control\n"
1678 "Cancel logging to file\n"
1679 "Logging file name\n")
1680 {
1681 return CMD_SUCCESS;
1682 }
1683
1684 ALIAS_SH (VTYSH_ALL,
1685 no_vtysh_log_file,
1686 no_vtysh_log_file_level_cmd,
1687 "no log file FILENAME LEVEL",
1688 NO_STR
1689 "Logging control\n"
1690 "Cancel logging to file\n"
1691 "Logging file name\n"
1692 "Logging level\n")
1693
1694 DEFUNSH (VTYSH_ALL,
1695 vtysh_log_monitor,
1696 vtysh_log_monitor_cmd,
1697 "log monitor",
1698 "Logging control\n"
1699 "Set terminal line (monitor) logging level\n")
1700 {
1701 return CMD_SUCCESS;
1702 }
1703
1704 DEFUNSH (VTYSH_ALL,
1705 vtysh_log_monitor_level,
1706 vtysh_log_monitor_level_cmd,
1707 "log monitor "LOG_LEVELS,
1708 "Logging control\n"
1709 "Set terminal line (monitor) logging level\n"
1710 LOG_LEVEL_DESC)
1711 {
1712 return CMD_SUCCESS;
1713 }
1714
1715 DEFUNSH (VTYSH_ALL,
1716 no_vtysh_log_monitor,
1717 no_vtysh_log_monitor_cmd,
1718 "no log monitor [LEVEL]",
1719 NO_STR
1720 "Logging control\n"
1721 "Disable terminal line (monitor) logging\n"
1722 "Logging level\n")
1723 {
1724 return CMD_SUCCESS;
1725 }
1726
1727 DEFUNSH (VTYSH_ALL,
1728 vtysh_log_syslog,
1729 vtysh_log_syslog_cmd,
1730 "log syslog",
1731 "Logging control\n"
1732 "Set syslog logging level\n")
1733 {
1734 return CMD_SUCCESS;
1735 }
1736
1737 DEFUNSH (VTYSH_ALL,
1738 vtysh_log_syslog_level,
1739 vtysh_log_syslog_level_cmd,
1740 "log syslog "LOG_LEVELS,
1741 "Logging control\n"
1742 "Set syslog logging level\n"
1743 LOG_LEVEL_DESC)
1744 {
1745 return CMD_SUCCESS;
1746 }
1747
1748 DEFUNSH (VTYSH_ALL,
1749 no_vtysh_log_syslog,
1750 no_vtysh_log_syslog_cmd,
1751 "no log syslog [LEVEL]",
1752 NO_STR
1753 "Logging control\n"
1754 "Cancel logging to syslog\n"
1755 "Logging level\n")
1756 {
1757 return CMD_SUCCESS;
1758 }
1759
1760 DEFUNSH (VTYSH_ALL,
1761 vtysh_log_facility,
1762 vtysh_log_facility_cmd,
1763 "log facility "LOG_FACILITIES,
1764 "Logging control\n"
1765 "Facility parameter for syslog messages\n"
1766 LOG_FACILITY_DESC)
1767
1768 {
1769 return CMD_SUCCESS;
1770 }
1771
1772 DEFUNSH (VTYSH_ALL,
1773 no_vtysh_log_facility,
1774 no_vtysh_log_facility_cmd,
1775 "no log facility [FACILITY]",
1776 NO_STR
1777 "Logging control\n"
1778 "Reset syslog facility to default (daemon)\n"
1779 "Syslog facility\n")
1780
1781 {
1782 return CMD_SUCCESS;
1783 }
1784
1785 DEFUNSH_DEPRECATED (VTYSH_ALL,
1786 vtysh_log_trap,
1787 vtysh_log_trap_cmd,
1788 "log trap "LOG_LEVELS,
1789 "Logging control\n"
1790 "(Deprecated) Set logging level and default for all destinations\n"
1791 LOG_LEVEL_DESC)
1792
1793 {
1794 return CMD_SUCCESS;
1795 }
1796
1797 DEFUNSH_DEPRECATED (VTYSH_ALL,
1798 no_vtysh_log_trap,
1799 no_vtysh_log_trap_cmd,
1800 "no log trap [LEVEL]",
1801 NO_STR
1802 "Logging control\n"
1803 "Permit all logging information\n"
1804 "Logging level\n")
1805 {
1806 return CMD_SUCCESS;
1807 }
1808
1809 DEFUNSH (VTYSH_ALL,
1810 vtysh_log_record_priority,
1811 vtysh_log_record_priority_cmd,
1812 "log record-priority",
1813 "Logging control\n"
1814 "Log the priority of the message within the message\n")
1815 {
1816 return CMD_SUCCESS;
1817 }
1818
1819 DEFUNSH (VTYSH_ALL,
1820 no_vtysh_log_record_priority,
1821 no_vtysh_log_record_priority_cmd,
1822 "no log record-priority",
1823 NO_STR
1824 "Logging control\n"
1825 "Do not log the priority of the message within the message\n")
1826 {
1827 return CMD_SUCCESS;
1828 }
1829
1830 DEFUNSH (VTYSH_ALL,
1831 vtysh_log_timestamp_precision,
1832 vtysh_log_timestamp_precision_cmd,
1833 "log timestamp precision <0-6>",
1834 "Logging control\n"
1835 "Timestamp configuration\n"
1836 "Set the timestamp precision\n"
1837 "Number of subsecond digits\n")
1838 {
1839 return CMD_SUCCESS;
1840 }
1841
1842 DEFUNSH (VTYSH_ALL,
1843 no_vtysh_log_timestamp_precision,
1844 no_vtysh_log_timestamp_precision_cmd,
1845 "no log timestamp precision",
1846 NO_STR
1847 "Logging control\n"
1848 "Timestamp configuration\n"
1849 "Reset the timestamp precision to the default value of 0\n")
1850 {
1851 return CMD_SUCCESS;
1852 }
1853
1854 DEFUNSH (VTYSH_ALL,
1855 vtysh_service_password_encrypt,
1856 vtysh_service_password_encrypt_cmd,
1857 "service password-encryption",
1858 "Set up miscellaneous service\n"
1859 "Enable encrypted passwords\n")
1860 {
1861 return CMD_SUCCESS;
1862 }
1863
1864 DEFUNSH (VTYSH_ALL,
1865 no_vtysh_service_password_encrypt,
1866 no_vtysh_service_password_encrypt_cmd,
1867 "no service password-encryption",
1868 NO_STR
1869 "Set up miscellaneous service\n"
1870 "Enable encrypted passwords\n")
1871 {
1872 return CMD_SUCCESS;
1873 }
1874
1875 DEFUNSH (VTYSH_ALL,
1876 vtysh_config_password,
1877 vtysh_password_cmd,
1878 "password (8|) WORD",
1879 "Assign the terminal connection password\n"
1880 "Specifies a HIDDEN password will follow\n"
1881 "dummy string \n"
1882 "The HIDDEN line password string\n")
1883 {
1884 return CMD_SUCCESS;
1885 }
1886
1887 DEFUNSH (VTYSH_ALL,
1888 vtysh_password_text,
1889 vtysh_password_text_cmd,
1890 "password LINE",
1891 "Assign the terminal connection password\n"
1892 "The UNENCRYPTED (cleartext) line password\n")
1893 {
1894 return CMD_SUCCESS;
1895 }
1896
1897 DEFUNSH (VTYSH_ALL,
1898 vtysh_config_enable_password,
1899 vtysh_enable_password_cmd,
1900 "enable password (8|) WORD",
1901 "Modify enable password parameters\n"
1902 "Assign the privileged level password\n"
1903 "Specifies a HIDDEN password will follow\n"
1904 "dummy string \n"
1905 "The HIDDEN 'enable' password string\n")
1906 {
1907 return CMD_SUCCESS;
1908 }
1909
1910 DEFUNSH (VTYSH_ALL,
1911 vtysh_enable_password_text,
1912 vtysh_enable_password_text_cmd,
1913 "enable password LINE",
1914 "Modify enable password parameters\n"
1915 "Assign the privileged level password\n"
1916 "The UNENCRYPTED (cleartext) 'enable' password\n")
1917 {
1918 return CMD_SUCCESS;
1919 }
1920
1921 DEFUNSH (VTYSH_ALL,
1922 no_vtysh_config_enable_password,
1923 no_vtysh_enable_password_cmd,
1924 "no enable password",
1925 NO_STR
1926 "Modify enable password parameters\n"
1927 "Assign the privileged level password\n")
1928 {
1929 return CMD_SUCCESS;
1930 }
1931
1932 DEFUN (vtysh_write_terminal,
1933 vtysh_write_terminal_cmd,
1934 "write terminal",
1935 "Write running configuration to memory, network, or terminal\n"
1936 "Write to terminal\n")
1937 {
1938 u_int i;
1939 char line[] = "write terminal\n";
1940 FILE *fp = NULL;
1941
1942 if (vtysh_pager_name)
1943 {
1944 fp = popen (vtysh_pager_name, "w");
1945 if (fp == NULL)
1946 {
1947 perror ("popen");
1948 exit (1);
1949 }
1950 }
1951 else
1952 fp = stdout;
1953
1954 vty_out (vty, "Building configuration...%s", VTY_NEWLINE);
1955 vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
1956 VTY_NEWLINE);
1957 vty_out (vty, "!%s", VTY_NEWLINE);
1958
1959 for (i = 0; i < array_size(vtysh_client); i++)
1960 vtysh_client_config (&vtysh_client[i], line);
1961
1962 /* Integrate vtysh specific configuration. */
1963 vtysh_config_write ();
1964
1965 vtysh_config_dump (fp);
1966
1967 if (vtysh_pager_name && fp)
1968 {
1969 fflush (fp);
1970 if (pclose (fp) == -1)
1971 {
1972 perror ("pclose");
1973 exit (1);
1974 }
1975 fp = NULL;
1976 }
1977
1978 vty_out (vty, "end%s", VTY_NEWLINE);
1979
1980 return CMD_SUCCESS;
1981 }
1982
1983 DEFUN (vtysh_integrated_config,
1984 vtysh_integrated_config_cmd,
1985 "service integrated-vtysh-config",
1986 "Set up miscellaneous service\n"
1987 "Write configuration into integrated file\n")
1988 {
1989 vtysh_writeconfig_integrated = 1;
1990 return CMD_SUCCESS;
1991 }
1992
1993 DEFUN (no_vtysh_integrated_config,
1994 no_vtysh_integrated_config_cmd,
1995 "no service integrated-vtysh-config",
1996 NO_STR
1997 "Set up miscellaneous service\n"
1998 "Write configuration into integrated file\n")
1999 {
2000 vtysh_writeconfig_integrated = 0;
2001 return CMD_SUCCESS;
2002 }
2003
2004 static int
2005 write_config_integrated(void)
2006 {
2007 u_int i;
2008 char line[] = "write terminal\n";
2009 FILE *fp;
2010 char *integrate_sav = NULL;
2011
2012 integrate_sav = malloc (strlen (integrate_default) +
2013 strlen (CONF_BACKUP_EXT) + 1);
2014 strcpy (integrate_sav, integrate_default);
2015 strcat (integrate_sav, CONF_BACKUP_EXT);
2016
2017 fprintf (stdout,"Building Configuration...\n");
2018
2019 /* Move current configuration file to backup config file. */
2020 unlink (integrate_sav);
2021 rename (integrate_default, integrate_sav);
2022 free (integrate_sav);
2023
2024 fp = fopen (integrate_default, "w");
2025 if (fp == NULL)
2026 {
2027 fprintf (stdout,"%% Can't open configuration file %s.\n",
2028 integrate_default);
2029 return CMD_SUCCESS;
2030 }
2031
2032 for (i = 0; i < array_size(vtysh_client); i++)
2033 vtysh_client_config (&vtysh_client[i], line);
2034
2035 vtysh_config_dump (fp);
2036
2037 fclose (fp);
2038
2039 if (chmod (integrate_default, CONFIGFILE_MASK) != 0)
2040 {
2041 fprintf (stdout,"%% Can't chmod configuration file %s: %s (%d)\n",
2042 integrate_default, safe_strerror(errno), errno);
2043 return CMD_WARNING;
2044 }
2045
2046 fprintf(stdout,"Integrated configuration saved to %s\n",integrate_default);
2047
2048 fprintf (stdout,"[OK]\n");
2049
2050 return CMD_SUCCESS;
2051 }
2052
2053 DEFUN (vtysh_write_memory,
2054 vtysh_write_memory_cmd,
2055 "write memory",
2056 "Write running configuration to memory, network, or terminal\n"
2057 "Write configuration to the file (same as write file)\n")
2058 {
2059 int ret = CMD_SUCCESS;
2060 char line[] = "write memory\n";
2061 u_int i;
2062
2063 /* If integrated Quagga.conf explicitely set. */
2064 if (vtysh_writeconfig_integrated)
2065 return write_config_integrated();
2066
2067 fprintf (stdout,"Building Configuration...\n");
2068
2069 for (i = 0; i < array_size(vtysh_client); i++)
2070 ret = vtysh_client_execute (&vtysh_client[i], line, stdout);
2071
2072 fprintf (stdout,"[OK]\n");
2073
2074 return ret;
2075 }
2076
2077 ALIAS (vtysh_write_memory,
2078 vtysh_copy_runningconfig_startupconfig_cmd,
2079 "copy running-config startup-config",
2080 "Copy from one file to another\n"
2081 "Copy from current system configuration\n"
2082 "Copy to startup configuration\n")
2083
2084 ALIAS (vtysh_write_memory,
2085 vtysh_write_file_cmd,
2086 "write file",
2087 "Write running configuration to memory, network, or terminal\n"
2088 "Write configuration to the file (same as write memory)\n")
2089
2090 ALIAS (vtysh_write_memory,
2091 vtysh_write_cmd,
2092 "write",
2093 "Write running configuration to memory, network, or terminal\n")
2094
2095 ALIAS (vtysh_write_terminal,
2096 vtysh_show_running_config_cmd,
2097 "show running-config",
2098 SHOW_STR
2099 "Current operating configuration\n")
2100
2101 DEFUN (vtysh_terminal_length,
2102 vtysh_terminal_length_cmd,
2103 "terminal length <0-512>",
2104 "Set terminal line parameters\n"
2105 "Set number of lines on a screen\n"
2106 "Number of lines on screen (0 for no pausing)\n")
2107 {
2108 int lines;
2109 char *endptr = NULL;
2110 char default_pager[10];
2111
2112 lines = strtol (argv[0], &endptr, 10);
2113 if (lines < 0 || lines > 512 || *endptr != '\0')
2114 {
2115 vty_out (vty, "length is malformed%s", VTY_NEWLINE);
2116 return CMD_WARNING;
2117 }
2118
2119 if (vtysh_pager_name)
2120 {
2121 free (vtysh_pager_name);
2122 vtysh_pager_name = NULL;
2123 }
2124
2125 if (lines != 0)
2126 {
2127 snprintf(default_pager, 10, "more -%i", lines);
2128 vtysh_pager_name = strdup (default_pager);
2129 }
2130
2131 return CMD_SUCCESS;
2132 }
2133
2134 DEFUN (vtysh_terminal_no_length,
2135 vtysh_terminal_no_length_cmd,
2136 "terminal no length",
2137 "Set terminal line parameters\n"
2138 NO_STR
2139 "Set number of lines on a screen\n")
2140 {
2141 if (vtysh_pager_name)
2142 {
2143 free (vtysh_pager_name);
2144 vtysh_pager_name = NULL;
2145 }
2146
2147 vtysh_pager_init();
2148 return CMD_SUCCESS;
2149 }
2150
2151 DEFUN (vtysh_show_daemons,
2152 vtysh_show_daemons_cmd,
2153 "show daemons",
2154 SHOW_STR
2155 "Show list of running daemons\n")
2156 {
2157 u_int i;
2158
2159 for (i = 0; i < array_size(vtysh_client); i++)
2160 if ( vtysh_client[i].fd >= 0 )
2161 vty_out(vty, " %s", vtysh_client[i].name);
2162 vty_out(vty, "%s", VTY_NEWLINE);
2163
2164 return CMD_SUCCESS;
2165 }
2166
2167 /* Execute command in child process. */
2168 static void
2169 execute_command (const char *command, int argc, const char *arg1,
2170 const char *arg2)
2171 {
2172 pid_t pid;
2173 int status;
2174
2175 /* Call fork(). */
2176 pid = fork ();
2177
2178 if (pid < 0)
2179 {
2180 /* Failure of fork(). */
2181 fprintf (stderr, "Can't fork: %s\n", safe_strerror (errno));
2182 exit (1);
2183 }
2184 else if (pid == 0)
2185 {
2186 /* This is child process. */
2187 switch (argc)
2188 {
2189 case 0:
2190 execlp (command, command, (const char *)NULL);
2191 break;
2192 case 1:
2193 execlp (command, command, arg1, (const char *)NULL);
2194 break;
2195 case 2:
2196 execlp (command, command, arg1, arg2, (const char *)NULL);
2197 break;
2198 }
2199
2200 /* When execlp suceed, this part is not executed. */
2201 fprintf (stderr, "Can't execute %s: %s\n", command, safe_strerror (errno));
2202 exit (1);
2203 }
2204 else
2205 {
2206 /* This is parent. */
2207 execute_flag = 1;
2208 wait4 (pid, &status, 0, NULL);
2209 execute_flag = 0;
2210 }
2211 }
2212
2213 DEFUN (vtysh_ping,
2214 vtysh_ping_cmd,
2215 "ping WORD",
2216 "Send echo messages\n"
2217 "Ping destination address or hostname\n")
2218 {
2219 execute_command ("ping", 1, argv[0], NULL);
2220 return CMD_SUCCESS;
2221 }
2222
2223 ALIAS (vtysh_ping,
2224 vtysh_ping_ip_cmd,
2225 "ping ip WORD",
2226 "Send echo messages\n"
2227 "IP echo\n"
2228 "Ping destination address or hostname\n")
2229
2230 DEFUN (vtysh_traceroute,
2231 vtysh_traceroute_cmd,
2232 "traceroute WORD",
2233 "Trace route to destination\n"
2234 "Trace route to destination address or hostname\n")
2235 {
2236 execute_command ("traceroute", 1, argv[0], NULL);
2237 return CMD_SUCCESS;
2238 }
2239
2240 ALIAS (vtysh_traceroute,
2241 vtysh_traceroute_ip_cmd,
2242 "traceroute ip WORD",
2243 "Trace route to destination\n"
2244 "IP trace\n"
2245 "Trace route to destination address or hostname\n")
2246
2247 #ifdef HAVE_IPV6
2248 DEFUN (vtysh_ping6,
2249 vtysh_ping6_cmd,
2250 "ping ipv6 WORD",
2251 "Send echo messages\n"
2252 "IPv6 echo\n"
2253 "Ping destination address or hostname\n")
2254 {
2255 execute_command ("ping6", 1, argv[0], NULL);
2256 return CMD_SUCCESS;
2257 }
2258
2259 DEFUN (vtysh_traceroute6,
2260 vtysh_traceroute6_cmd,
2261 "traceroute ipv6 WORD",
2262 "Trace route to destination\n"
2263 "IPv6 trace\n"
2264 "Trace route to destination address or hostname\n")
2265 {
2266 execute_command ("traceroute6", 1, argv[0], NULL);
2267 return CMD_SUCCESS;
2268 }
2269 #endif
2270
2271 DEFUN (vtysh_telnet,
2272 vtysh_telnet_cmd,
2273 "telnet WORD",
2274 "Open a telnet connection\n"
2275 "IP address or hostname of a remote system\n")
2276 {
2277 execute_command ("telnet", 1, argv[0], NULL);
2278 return CMD_SUCCESS;
2279 }
2280
2281 DEFUN (vtysh_telnet_port,
2282 vtysh_telnet_port_cmd,
2283 "telnet WORD PORT",
2284 "Open a telnet connection\n"
2285 "IP address or hostname of a remote system\n"
2286 "TCP Port number\n")
2287 {
2288 execute_command ("telnet", 2, argv[0], argv[1]);
2289 return CMD_SUCCESS;
2290 }
2291
2292 DEFUN (vtysh_ssh,
2293 vtysh_ssh_cmd,
2294 "ssh WORD",
2295 "Open an ssh connection\n"
2296 "[user@]host\n")
2297 {
2298 execute_command ("ssh", 1, argv[0], NULL);
2299 return CMD_SUCCESS;
2300 }
2301
2302 DEFUN (vtysh_start_shell,
2303 vtysh_start_shell_cmd,
2304 "start-shell",
2305 "Start UNIX shell\n")
2306 {
2307 execute_command ("sh", 0, NULL, NULL);
2308 return CMD_SUCCESS;
2309 }
2310
2311 DEFUN (vtysh_start_bash,
2312 vtysh_start_bash_cmd,
2313 "start-shell bash",
2314 "Start UNIX shell\n"
2315 "Start bash\n")
2316 {
2317 execute_command ("bash", 0, NULL, NULL);
2318 return CMD_SUCCESS;
2319 }
2320
2321 DEFUN (vtysh_start_zsh,
2322 vtysh_start_zsh_cmd,
2323 "start-shell zsh",
2324 "Start UNIX shell\n"
2325 "Start Z shell\n")
2326 {
2327 execute_command ("zsh", 0, NULL, NULL);
2328 return CMD_SUCCESS;
2329 }
2330
2331 static void
2332 vtysh_install_default (enum node_type node)
2333 {
2334 install_element (node, &config_list_cmd);
2335 }
2336
2337 /* Making connection to protocol daemon. */
2338 static int
2339 vtysh_connect (struct vtysh_client *vclient)
2340 {
2341 int ret;
2342 int sock, len;
2343 struct sockaddr_un addr;
2344 struct stat s_stat;
2345
2346 /* Stat socket to see if we have permission to access it. */
2347 ret = stat (vclient->path, &s_stat);
2348 if (ret < 0 && errno != ENOENT)
2349 {
2350 fprintf (stderr, "vtysh_connect(%s): stat = %s\n",
2351 vclient->path, safe_strerror(errno));
2352 exit(1);
2353 }
2354
2355 if (ret >= 0)
2356 {
2357 if (! S_ISSOCK(s_stat.st_mode))
2358 {
2359 fprintf (stderr, "vtysh_connect(%s): Not a socket\n",
2360 vclient->path);
2361 exit (1);
2362 }
2363
2364 }
2365
2366 sock = socket (AF_UNIX, SOCK_STREAM, 0);
2367 if (sock < 0)
2368 {
2369 #ifdef DEBUG
2370 fprintf(stderr, "vtysh_connect(%s): socket = %s\n", vclient->path,
2371 safe_strerror(errno));
2372 #endif /* DEBUG */
2373 return -1;
2374 }
2375
2376 memset (&addr, 0, sizeof (struct sockaddr_un));
2377 addr.sun_family = AF_UNIX;
2378 strncpy (addr.sun_path, vclient->path, strlen (vclient->path));
2379 #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
2380 len = addr.sun_len = SUN_LEN(&addr);
2381 #else
2382 len = sizeof (addr.sun_family) + strlen (addr.sun_path);
2383 #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
2384
2385 ret = connect (sock, (struct sockaddr *) &addr, len);
2386 if (ret < 0)
2387 {
2388 #ifdef DEBUG
2389 fprintf(stderr, "vtysh_connect(%s): connect = %s\n", vclient->path,
2390 safe_strerror(errno));
2391 #endif /* DEBUG */
2392 close (sock);
2393 return -1;
2394 }
2395 vclient->fd = sock;
2396
2397 return 0;
2398 }
2399
2400 /* Return true if str begins with prefix, else return false */
2401 static int
2402 begins_with(const char *str, const char *prefix)
2403 {
2404 if (!str || !prefix)
2405 return 0;
2406 size_t lenstr = strlen(str);
2407 size_t lenprefix = strlen(prefix);
2408 if (lenprefix > lenstr)
2409 return 0;
2410 return strncmp(str, prefix, lenprefix) == 0;
2411 }
2412
2413 /* Return true if str ends with suffix, else return false */
2414 static int
2415 ends_with(const char *str, const char *suffix)
2416 {
2417 if (!str || !suffix)
2418 return 0;
2419 size_t lenstr = strlen(str);
2420 size_t lensuffix = strlen(suffix);
2421 if (lensuffix > lenstr)
2422 return 0;
2423 return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
2424 }
2425
2426 static void
2427 vtysh_client_sorted_insert (struct vtysh_client *head_client,
2428 struct vtysh_client *client)
2429 {
2430 struct vtysh_client *prev_node, *current_node;
2431
2432 prev_node = head_client;
2433 current_node = head_client->next;
2434 while (current_node)
2435 {
2436 if (strcmp(current_node->path, client->path) > 0)
2437 break;
2438
2439 prev_node = current_node;
2440 current_node = current_node->next;
2441 }
2442 client->next = current_node;
2443 prev_node->next = client;
2444 }
2445
2446 #define MAXIMUM_INSTANCES 10
2447
2448 static void
2449 vtysh_update_all_insances(struct vtysh_client * head_client)
2450 {
2451 struct vtysh_client *client;
2452 char *ptr;
2453 DIR *dir;
2454 struct dirent *file;
2455 int n = 0;
2456
2457 if (head_client->flag != VTYSH_OSPFD) return;
2458
2459 /* ls /var/run/quagga/ and look for all files ending in .vty */
2460 dir = opendir("/var/run/quagga/");
2461 if (dir)
2462 {
2463 while ((file = readdir(dir)) != NULL)
2464 {
2465 if (begins_with(file->d_name, "ospfd-") && ends_with(file->d_name, ".vty"))
2466 {
2467 if (n == MAXIMUM_INSTANCES)
2468 {
2469 fprintf(stderr,
2470 "Parsing /var/run/quagga/, client limit(%d) reached!\n", n);
2471 break;
2472 }
2473 client = (struct vtysh_client *) malloc(sizeof(struct vtysh_client));
2474 client->fd = -1;
2475 client->name = "ospfd";
2476 client->flag = VTYSH_OSPFD;
2477 ptr = (char *) malloc(100);
2478 sprintf(ptr, "/var/run/quagga/%s", file->d_name);
2479 client->path = (const char *)ptr;
2480 client->next = NULL;
2481 vtysh_client_sorted_insert(head_client, client);
2482 n++;
2483 }
2484 }
2485 closedir(dir);
2486 }
2487 }
2488
2489 int
2490 vtysh_connect_all_instances (struct vtysh_client *head_client)
2491 {
2492 struct vtysh_client *client;
2493 int rc = 0;
2494
2495 vtysh_update_all_insances(head_client);
2496
2497 client = head_client->next;
2498 while (client)
2499 {
2500 if (vtysh_connect(client) == 0)
2501 rc++;
2502 client = client->next;
2503 }
2504
2505 return rc;
2506 }
2507
2508 int
2509 vtysh_connect_all(const char *daemon_name)
2510 {
2511 u_int i;
2512 int rc = 0;
2513 int matches = 0;
2514
2515 for (i = 0; i < array_size(vtysh_client); i++)
2516 {
2517 if (!daemon_name || !strcmp(daemon_name, vtysh_client[i].name))
2518 {
2519 matches++;
2520 if (vtysh_connect(&vtysh_client[i]) == 0)
2521 rc++;
2522 /* We need direct access to ripd in vtysh_exit_ripd_only. */
2523 if (vtysh_client[i].flag == VTYSH_RIPD)
2524 ripd_client = &vtysh_client[i];
2525
2526 rc += vtysh_connect_all_instances(&vtysh_client[i]);
2527 }
2528 }
2529 if (!matches)
2530 fprintf(stderr, "Error: no daemons match name %s!\n", daemon_name);
2531 return rc;
2532 }
2533
2534 /* To disable readline's filename completion. */
2535 static char *
2536 vtysh_completion_entry_function (const char *ignore, int invoking_key)
2537 {
2538 return NULL;
2539 }
2540
2541 void
2542 vtysh_readline_init (void)
2543 {
2544 /* readline related settings. */
2545 rl_bind_key ('?', (rl_command_func_t *) vtysh_rl_describe);
2546 rl_completion_entry_function = vtysh_completion_entry_function;
2547 rl_attempted_completion_function = (rl_completion_func_t *)new_completion;
2548 }
2549
2550 char *
2551 vtysh_prompt (void)
2552 {
2553 static struct utsname names;
2554 static char buf[100];
2555 const char*hostname;
2556 extern struct host host;
2557
2558 hostname = host.name;
2559
2560 if (!hostname)
2561 {
2562 if (!names.nodename[0])
2563 uname (&names);
2564 hostname = names.nodename;
2565 }
2566
2567 snprintf (buf, sizeof buf, cmd_prompt (vty->node), hostname);
2568
2569 return buf;
2570 }
2571
2572 void
2573 vtysh_init_vty (void)
2574 {
2575 /* Make vty structure. */
2576 vty = vty_new ();
2577 vty->type = VTY_SHELL;
2578 vty->node = VIEW_NODE;
2579
2580 /* Initialize commands. */
2581 cmd_init (0);
2582
2583 /* Install nodes. */
2584 install_node (&bgp_node, NULL);
2585 install_node (&rip_node, NULL);
2586 install_node (&interface_node, NULL);
2587 install_node (&rmap_node, NULL);
2588 install_node (&zebra_node, NULL);
2589 install_node (&bgp_vpnv4_node, NULL);
2590 install_node (&bgp_ipv4_node, NULL);
2591 install_node (&bgp_ipv4m_node, NULL);
2592 /* #ifdef HAVE_IPV6 */
2593 install_node (&bgp_ipv6_node, NULL);
2594 install_node (&bgp_ipv6m_node, NULL);
2595 /* #endif */
2596 install_node (&ospf_node, NULL);
2597 /* #ifdef HAVE_IPV6 */
2598 install_node (&ripng_node, NULL);
2599 install_node (&ospf6_node, NULL);
2600 /* #endif */
2601 install_node (&babel_node, NULL);
2602 install_node (&keychain_node, NULL);
2603 install_node (&keychain_key_node, NULL);
2604 install_node (&isis_node, NULL);
2605 install_node (&vty_node, NULL);
2606
2607 vtysh_install_default (VIEW_NODE);
2608 vtysh_install_default (ENABLE_NODE);
2609 vtysh_install_default (CONFIG_NODE);
2610 vtysh_install_default (BGP_NODE);
2611 vtysh_install_default (RIP_NODE);
2612 vtysh_install_default (INTERFACE_NODE);
2613 vtysh_install_default (RMAP_NODE);
2614 vtysh_install_default (ZEBRA_NODE);
2615 vtysh_install_default (BGP_VPNV4_NODE);
2616 vtysh_install_default (BGP_IPV4_NODE);
2617 vtysh_install_default (BGP_IPV4M_NODE);
2618 vtysh_install_default (BGP_IPV6_NODE);
2619 vtysh_install_default (BGP_IPV6M_NODE);
2620 vtysh_install_default (OSPF_NODE);
2621 vtysh_install_default (RIPNG_NODE);
2622 vtysh_install_default (OSPF6_NODE);
2623 vtysh_install_default (BABEL_NODE);
2624 vtysh_install_default (ISIS_NODE);
2625 vtysh_install_default (KEYCHAIN_NODE);
2626 vtysh_install_default (KEYCHAIN_KEY_NODE);
2627 vtysh_install_default (VTY_NODE);
2628
2629 install_element (VIEW_NODE, &vtysh_enable_cmd);
2630 install_element (ENABLE_NODE, &vtysh_config_terminal_cmd);
2631 install_element (ENABLE_NODE, &vtysh_disable_cmd);
2632
2633 /* "exit" command. */
2634 install_element (VIEW_NODE, &vtysh_exit_all_cmd);
2635 install_element (VIEW_NODE, &vtysh_quit_all_cmd);
2636 install_element (CONFIG_NODE, &vtysh_exit_all_cmd);
2637 /* install_element (CONFIG_NODE, &vtysh_quit_all_cmd); */
2638 install_element (ENABLE_NODE, &vtysh_exit_all_cmd);
2639 install_element (ENABLE_NODE, &vtysh_quit_all_cmd);
2640 install_element (RIP_NODE, &vtysh_exit_ripd_cmd);
2641 install_element (RIP_NODE, &vtysh_quit_ripd_cmd);
2642 install_element (RIPNG_NODE, &vtysh_exit_ripngd_cmd);
2643 install_element (RIPNG_NODE, &vtysh_quit_ripngd_cmd);
2644 install_element (OSPF_NODE, &vtysh_exit_ospfd_cmd);
2645 install_element (OSPF_NODE, &vtysh_quit_ospfd_cmd);
2646 install_element (OSPF6_NODE, &vtysh_exit_ospf6d_cmd);
2647 install_element (OSPF6_NODE, &vtysh_quit_ospf6d_cmd);
2648 install_element (BGP_NODE, &vtysh_exit_bgpd_cmd);
2649 install_element (BGP_NODE, &vtysh_quit_bgpd_cmd);
2650 install_element (BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd);
2651 install_element (BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd);
2652 install_element (BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd);
2653 install_element (BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd);
2654 install_element (BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd);
2655 install_element (BGP_IPV4M_NODE, &vtysh_quit_bgpd_cmd);
2656 install_element (BGP_IPV6_NODE, &vtysh_exit_bgpd_cmd);
2657 install_element (BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd);
2658 install_element (BGP_IPV6M_NODE, &vtysh_exit_bgpd_cmd);
2659 install_element (BGP_IPV6M_NODE, &vtysh_quit_bgpd_cmd);
2660 install_element (ISIS_NODE, &vtysh_exit_isisd_cmd);
2661 install_element (ISIS_NODE, &vtysh_quit_isisd_cmd);
2662 install_element (KEYCHAIN_NODE, &vtysh_exit_ripd_cmd);
2663 install_element (KEYCHAIN_NODE, &vtysh_quit_ripd_cmd);
2664 install_element (KEYCHAIN_KEY_NODE, &vtysh_exit_ripd_cmd);
2665 install_element (KEYCHAIN_KEY_NODE, &vtysh_quit_ripd_cmd);
2666 install_element (RMAP_NODE, &vtysh_exit_rmap_cmd);
2667 install_element (RMAP_NODE, &vtysh_quit_rmap_cmd);
2668 install_element (VTY_NODE, &vtysh_exit_line_vty_cmd);
2669 install_element (VTY_NODE, &vtysh_quit_line_vty_cmd);
2670
2671 /* "end" command. */
2672 install_element (CONFIG_NODE, &vtysh_end_all_cmd);
2673 install_element (ENABLE_NODE, &vtysh_end_all_cmd);
2674 install_element (RIP_NODE, &vtysh_end_all_cmd);
2675 install_element (RIPNG_NODE, &vtysh_end_all_cmd);
2676 install_element (OSPF_NODE, &vtysh_end_all_cmd);
2677 install_element (OSPF6_NODE, &vtysh_end_all_cmd);
2678 install_element (BABEL_NODE, &vtysh_end_all_cmd);
2679 install_element (BGP_NODE, &vtysh_end_all_cmd);
2680 install_element (BGP_IPV4_NODE, &vtysh_end_all_cmd);
2681 install_element (BGP_IPV4M_NODE, &vtysh_end_all_cmd);
2682 install_element (BGP_VPNV4_NODE, &vtysh_end_all_cmd);
2683 install_element (BGP_IPV6_NODE, &vtysh_end_all_cmd);
2684 install_element (BGP_IPV6M_NODE, &vtysh_end_all_cmd);
2685 install_element (ISIS_NODE, &vtysh_end_all_cmd);
2686 install_element (KEYCHAIN_NODE, &vtysh_end_all_cmd);
2687 install_element (KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
2688 install_element (RMAP_NODE, &vtysh_end_all_cmd);
2689 install_element (VTY_NODE, &vtysh_end_all_cmd);
2690
2691 install_element (INTERFACE_NODE, &interface_desc_cmd);
2692 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
2693 install_element (INTERFACE_NODE, &vtysh_end_all_cmd);
2694 install_element (INTERFACE_NODE, &vtysh_exit_interface_cmd);
2695 install_element (INTERFACE_NODE, &vtysh_quit_interface_cmd);
2696 install_element (CONFIG_NODE, &router_rip_cmd);
2697 #ifdef HAVE_IPV6
2698 install_element (CONFIG_NODE, &router_ripng_cmd);
2699 #endif
2700 install_element (CONFIG_NODE, &router_ospf_cmd);
2701 install_element (CONFIG_NODE, &router_ospf_instance_cmd);
2702 #ifdef HAVE_IPV6
2703 install_element (CONFIG_NODE, &router_ospf6_cmd);
2704 #endif
2705 install_element (CONFIG_NODE, &router_babel_cmd);
2706 install_element (CONFIG_NODE, &router_isis_cmd);
2707 install_element (CONFIG_NODE, &router_bgp_cmd);
2708 install_element (CONFIG_NODE, &router_bgp_view_cmd);
2709 install_element (BGP_NODE, &address_family_vpnv4_cmd);
2710 install_element (BGP_NODE, &address_family_vpnv4_unicast_cmd);
2711 install_element (BGP_NODE, &address_family_ipv4_unicast_cmd);
2712 install_element (BGP_NODE, &address_family_ipv4_multicast_cmd);
2713 #ifdef HAVE_IPV6
2714 install_element (BGP_NODE, &address_family_ipv6_cmd);
2715 install_element (BGP_NODE, &address_family_ipv6_unicast_cmd);
2716 install_element (BGP_NODE, &address_family_ipv6_multicast_cmd);
2717 #endif
2718 install_element (BGP_VPNV4_NODE, &exit_address_family_cmd);
2719 install_element (BGP_IPV4_NODE, &exit_address_family_cmd);
2720 install_element (BGP_IPV4M_NODE, &exit_address_family_cmd);
2721 install_element (BGP_IPV6_NODE, &exit_address_family_cmd);
2722 install_element (BGP_IPV6M_NODE, &exit_address_family_cmd);
2723 install_element (CONFIG_NODE, &key_chain_cmd);
2724 install_element (CONFIG_NODE, &route_map_cmd);
2725 install_element (CONFIG_NODE, &vtysh_line_vty_cmd);
2726 install_element (KEYCHAIN_NODE, &key_cmd);
2727 install_element (KEYCHAIN_NODE, &key_chain_cmd);
2728 install_element (KEYCHAIN_KEY_NODE, &key_chain_cmd);
2729 install_element (CONFIG_NODE, &vtysh_interface_cmd);
2730 install_element (CONFIG_NODE, &vtysh_no_interface_cmd);
2731 install_element (ENABLE_NODE, &vtysh_show_running_config_cmd);
2732 install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd);
2733 install_element (ENABLE_NODE, &vtysh_write_file_cmd);
2734 install_element (ENABLE_NODE, &vtysh_write_cmd);
2735
2736 /* "write terminal" command. */
2737 install_element (ENABLE_NODE, &vtysh_write_terminal_cmd);
2738
2739 install_element (CONFIG_NODE, &vtysh_integrated_config_cmd);
2740 install_element (CONFIG_NODE, &no_vtysh_integrated_config_cmd);
2741
2742 /* "write memory" command. */
2743 install_element (ENABLE_NODE, &vtysh_write_memory_cmd);
2744
2745 install_element (VIEW_NODE, &vtysh_terminal_length_cmd);
2746 install_element (ENABLE_NODE, &vtysh_terminal_length_cmd);
2747 install_element (VIEW_NODE, &vtysh_terminal_no_length_cmd);
2748 install_element (ENABLE_NODE, &vtysh_terminal_no_length_cmd);
2749 install_element (VIEW_NODE, &vtysh_show_daemons_cmd);
2750 install_element (ENABLE_NODE, &vtysh_show_daemons_cmd);
2751
2752 install_element (VIEW_NODE, &vtysh_ping_cmd);
2753 install_element (VIEW_NODE, &vtysh_ping_ip_cmd);
2754 install_element (VIEW_NODE, &vtysh_traceroute_cmd);
2755 install_element (VIEW_NODE, &vtysh_traceroute_ip_cmd);
2756 #ifdef HAVE_IPV6
2757 install_element (VIEW_NODE, &vtysh_ping6_cmd);
2758 install_element (VIEW_NODE, &vtysh_traceroute6_cmd);
2759 #endif
2760 install_element (VIEW_NODE, &vtysh_telnet_cmd);
2761 install_element (VIEW_NODE, &vtysh_telnet_port_cmd);
2762 install_element (VIEW_NODE, &vtysh_ssh_cmd);
2763 install_element (ENABLE_NODE, &vtysh_ping_cmd);
2764 install_element (ENABLE_NODE, &vtysh_ping_ip_cmd);
2765 install_element (ENABLE_NODE, &vtysh_traceroute_cmd);
2766 install_element (ENABLE_NODE, &vtysh_traceroute_ip_cmd);
2767 #ifdef HAVE_IPV6
2768 install_element (ENABLE_NODE, &vtysh_ping6_cmd);
2769 install_element (ENABLE_NODE, &vtysh_traceroute6_cmd);
2770 #endif
2771 install_element (ENABLE_NODE, &vtysh_telnet_cmd);
2772 install_element (ENABLE_NODE, &vtysh_telnet_port_cmd);
2773 install_element (ENABLE_NODE, &vtysh_ssh_cmd);
2774 install_element (ENABLE_NODE, &vtysh_start_shell_cmd);
2775 install_element (ENABLE_NODE, &vtysh_start_bash_cmd);
2776 install_element (ENABLE_NODE, &vtysh_start_zsh_cmd);
2777
2778 install_element (VIEW_NODE, &vtysh_show_memory_cmd);
2779 install_element (ENABLE_NODE, &vtysh_show_memory_cmd);
2780
2781 /* Logging */
2782 install_element (ENABLE_NODE, &vtysh_show_logging_cmd);
2783 install_element (VIEW_NODE, &vtysh_show_logging_cmd);
2784 install_element (CONFIG_NODE, &vtysh_log_stdout_cmd);
2785 install_element (CONFIG_NODE, &vtysh_log_stdout_level_cmd);
2786 install_element (CONFIG_NODE, &no_vtysh_log_stdout_cmd);
2787 install_element (CONFIG_NODE, &vtysh_log_file_cmd);
2788 install_element (CONFIG_NODE, &vtysh_log_file_level_cmd);
2789 install_element (CONFIG_NODE, &no_vtysh_log_file_cmd);
2790 install_element (CONFIG_NODE, &no_vtysh_log_file_level_cmd);
2791 install_element (CONFIG_NODE, &vtysh_log_monitor_cmd);
2792 install_element (CONFIG_NODE, &vtysh_log_monitor_level_cmd);
2793 install_element (CONFIG_NODE, &no_vtysh_log_monitor_cmd);
2794 install_element (CONFIG_NODE, &vtysh_log_syslog_cmd);
2795 install_element (CONFIG_NODE, &vtysh_log_syslog_level_cmd);
2796 install_element (CONFIG_NODE, &no_vtysh_log_syslog_cmd);
2797 install_element (CONFIG_NODE, &vtysh_log_trap_cmd);
2798 install_element (CONFIG_NODE, &no_vtysh_log_trap_cmd);
2799 install_element (CONFIG_NODE, &vtysh_log_facility_cmd);
2800 install_element (CONFIG_NODE, &no_vtysh_log_facility_cmd);
2801 install_element (CONFIG_NODE, &vtysh_log_record_priority_cmd);
2802 install_element (CONFIG_NODE, &no_vtysh_log_record_priority_cmd);
2803 install_element (CONFIG_NODE, &vtysh_log_timestamp_precision_cmd);
2804 install_element (CONFIG_NODE, &no_vtysh_log_timestamp_precision_cmd);
2805
2806 install_element (CONFIG_NODE, &vtysh_service_password_encrypt_cmd);
2807 install_element (CONFIG_NODE, &no_vtysh_service_password_encrypt_cmd);
2808
2809 install_element (CONFIG_NODE, &vtysh_password_cmd);
2810 install_element (CONFIG_NODE, &vtysh_password_text_cmd);
2811 install_element (CONFIG_NODE, &vtysh_enable_password_cmd);
2812 install_element (CONFIG_NODE, &vtysh_enable_password_text_cmd);
2813 install_element (CONFIG_NODE, &no_vtysh_enable_password_cmd);
2814
2815 }