blob: be1f03e4d5dc14de4cfc86c3808a600dd7a94fc8 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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 "command.h"
34#include "memory.h"
35#include "vtysh/vtysh.h"
36
37/* Struct VTY. */
38struct vty *vty;
39
40/* VTY shell pager name. */
41char *vtysh_pager_name = NULL;
42
43/* VTY shell client structure. */
44struct vtysh_client
45{
46 int fd;
47} vtysh_client[VTYSH_INDEX_MAX];
48
49/* When '^Z' is received from vty, move down to the enable mode. */
50int
51vtysh_end ()
52{
53 switch (vty->node)
54 {
55 case VIEW_NODE:
56 case ENABLE_NODE:
57 /* Nothing to do. */
58 break;
59 default:
60 vty->node = ENABLE_NODE;
61 break;
62 }
63 return CMD_SUCCESS;
64}
65
66DEFUNSH (VTYSH_ALL,
67 vtysh_end_all,
68 vtysh_end_all_cmd,
69 "end",
70 "End current mode and down to previous mode\n")
71{
72 return vtysh_end (vty);
73}
74
75DEFUNSH (VTYSH_ALL,
76 vtysh_log_stdout,
77 vtysh_log_stdout_cmd,
78 "log stdout",
79 "Logging control\n"
80 "Logging goes to stdout\n")
81{
82 return CMD_SUCCESS;
83}
84
85DEFUNSH (VTYSH_ALL,
86 no_vtysh_log_stdout,
87 no_vtysh_log_stdout_cmd,
88 "no log stdout",
89 NO_STR
90 "Logging control\n"
91 "Logging goes to stdout\n")
92{
93 return CMD_SUCCESS;
94}
95
96DEFUNSH (VTYSH_ALL,
97 vtysh_log_file,
98 vtysh_log_file_cmd,
99 "log file FILENAME",
100 "Logging control\n"
101 "Logging to file\n"
102 "Logging filename\n")
103{
104 return CMD_SUCCESS;
105}
106
107DEFUNSH (VTYSH_ALL,
108 no_vtysh_log_file,
109 no_vtysh_log_file_cmd,
110 "no log file [FILENAME]",
111 NO_STR
112 "Logging control\n"
113 "Cancel logging to file\n"
114 "Logging file name\n")
115{
116 return CMD_SUCCESS;
117}
118
119DEFUNSH (VTYSH_ALL,
120 vtysh_log_syslog,
121 vtysh_log_syslog_cmd,
122 "log syslog",
123 "Logging control\n"
124 "Logging goes to syslog\n")
125{
126 return CMD_SUCCESS;
127}
128
129DEFUNSH (VTYSH_ALL,
130 no_vtysh_log_syslog,
131 no_vtysh_log_syslog_cmd,
132 "no log syslog",
133 NO_STR
134 "Logging control\n"
135 "Cancel logging to syslog\n")
136{
137 return CMD_SUCCESS;
138}
139
140DEFUNSH (VTYSH_ALL,
141 vtysh_log_trap,
142 vtysh_log_trap_cmd,
143 "log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)",
144 "Logging control\n"
145 "Limit logging to specifed level\n")
146{
147 return CMD_SUCCESS;
148}
149
150DEFUNSH (VTYSH_ALL,
151 no_vtysh_log_trap,
152 no_vtysh_log_trap_cmd,
153 "no log trap",
154 NO_STR
155 "Logging control\n"
156 "Permit all logging information\n")
157{
158 return CMD_SUCCESS;
159}
160
161DEFUNSH (VTYSH_ALL,
162 vtysh_log_record_priority,
163 vtysh_log_record_priority_cmd,
164 "log record-priority",
165 "Logging control\n"
166 "Log the priority of the message within the message\n")
167{
168 return CMD_SUCCESS;
169}
170
171DEFUNSH (VTYSH_ALL,
172 no_vtysh_log_record_priority,
173 no_vtysh_log_record_priority_cmd,
174 "no log record-priority",
175 NO_STR
176 "Logging control\n"
177 "Do not log the priority of the message within the message\n")
178{
179 return CMD_SUCCESS;
180}
181
182void
183vclient_close (struct vtysh_client *vclient)
184{
185 if (vclient->fd > 0)
186 close (vclient->fd);
187 vclient->fd = -1;
188}
189
190
191/* Following filled with debug code to trace a problematic condition
192 under load - it SHOULD handle it.
193*/
194#define ERR_WHERE_STRING "vtysh(): vtysh_client_config(): "
195int
196vtysh_client_config (struct vtysh_client *vclient, char *line)
197{
198 int ret;
199 char *buf;
200 size_t bufsz;
201 char *pbuf;
202 size_t left;
203 char *eoln;
204 int nbytes;
205 int i;
206 int readln;
207
208 if (vclient->fd < 0)
209 return CMD_SUCCESS;
210
211 ret = write (vclient->fd, line, strlen (line) + 1);
212 if (ret <= 0)
213 {
214 vclient_close (vclient);
215 return CMD_SUCCESS;
216 }
217
218 /* Allow enough room for buffer to read more than a few pages from socket
219 */
paule3d29b52003-01-23 18:05:42 +0000220 bufsz = 5 * getpagesize() + 1;
paul718e3742002-12-13 20:15:29 +0000221 buf = XMALLOC(MTYPE_TMP, bufsz);
222 memset(buf, 0, bufsz);
223 pbuf = buf;
224
225 while (1)
226 {
227 if (pbuf >= ((buf + bufsz) -1))
228 {
229 fprintf (stderr, ERR_WHERE_STRING \
230 "warning - pbuf beyond buffer end.\n");
231 return CMD_WARNING;
232 }
233
234 readln = (buf + bufsz) - pbuf - 1;
235 nbytes = read (vclient->fd, pbuf, readln);
236
237 if (nbytes <= 0)
238 {
239
240 if (errno == EINTR)
241 continue;
242
243 fprintf(stderr, ERR_WHERE_STRING "(%u)", errno);
244 perror("");
245
246 if (errno == EAGAIN || errno == EIO)
247 continue;
248
249 vclient_close (vclient);
250 XFREE(MTYPE_TMP, buf);
251 return CMD_SUCCESS;
252 }
253
254 pbuf[nbytes] = '\0';
255
256 if (nbytes >= 4)
257 {
258 i = nbytes - 4;
259 if (pbuf[i] == '\0' && pbuf[i + 1] == '\0' && pbuf[i + 2] == '\0')
260 {
261 ret = pbuf[i + 3];
262 break;
263 }
264 }
265 pbuf += nbytes;
266
267 /* See if a line exists in buffer, if so parse and consume it, and
268 reset read position */
269 if ((eoln = strrchr(buf, '\n')) == NULL)
270 continue;
271
272 if (eoln >= ((buf + bufsz) - 1))
273 {
274 fprintf (stderr, ERR_WHERE_STRING \
275 "warning - eoln beyond buffer end.\n");
276 }
277 vtysh_config_parse(buf);
278
279 eoln++;
280 left = (size_t)(buf + bufsz - eoln);
281 memmove(buf, eoln, left);
282 buf[bufsz-1] = '\0';
283 pbuf = buf + strlen(buf);
284 }
285
286 /* parse anything left in the buffer */
287 vtysh_config_parse (buf);
288
289 XFREE(MTYPE_TMP, buf);
290 return ret;
291}
292
293int
294vtysh_client_execute (struct vtysh_client *vclient, char *line, FILE *fp)
295{
296 int ret;
297 char buf[1001];
298 int nbytes;
299 int i;
300
301 if (vclient->fd < 0)
302 return CMD_SUCCESS;
303
304 ret = write (vclient->fd, line, strlen (line) + 1);
305 if (ret <= 0)
306 {
307 vclient_close (vclient);
308 return CMD_SUCCESS;
309 }
310
311 while (1)
312 {
313 nbytes = read (vclient->fd, buf, sizeof(buf)-1);
314
315 if (nbytes <= 0 && errno != EINTR)
316 {
317 vclient_close (vclient);
318 return CMD_SUCCESS;
319 }
320
321 if (nbytes > 0)
322 {
323 buf[nbytes] = '\0';
324 fprintf (fp, "%s", buf);
325 fflush (fp);
326
327 if (nbytes >= 4)
328 {
329 i = nbytes - 4;
330 if (buf[i] == '\0' && buf[i + 1] == '\0' && buf[i + 2] == '\0')
331 {
332 ret = buf[i + 3];
333 break;
334 }
335 }
336 }
337 }
338 return ret;
339}
340
341void
342vtysh_exit_ripd_only ()
343{
344 vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP], "exit", stdout);
345}
346
347
348void
349vtysh_pager_init ()
350{
351 vtysh_pager_name = getenv ("VTYSH_PAGER");
352 if (! vtysh_pager_name)
paula805cc22003-05-01 14:29:48 +0000353 vtysh_pager_name = getenv ("PAGER");
354 if (! vtysh_pager_name)
paul718e3742002-12-13 20:15:29 +0000355 vtysh_pager_name = "more";
356}
357
358/* Command execution over the vty interface. */
359void
360vtysh_execute_func (char *line, int pager)
361{
362 int ret, cmd_stat;
363 vector vline;
364 struct cmd_element *cmd;
365 FILE *fp = NULL;
paula805cc22003-05-01 14:29:48 +0000366 int closepager=0;
paul718e3742002-12-13 20:15:29 +0000367
368 /* Split readline string up into the vector */
369 vline = cmd_make_strvec (line);
370
371 if (vline == NULL)
372 return;
373
374 ret = cmd_execute_command (vline, vty, &cmd);
375
376 cmd_free_strvec (vline);
377
378 switch (ret)
379 {
380 case CMD_WARNING:
381 if (vty->type == VTY_FILE)
paul4fc01e62002-12-13 20:49:00 +0000382 fprintf (stdout,"Warning...\n");
paul718e3742002-12-13 20:15:29 +0000383 break;
384 case CMD_ERR_AMBIGUOUS:
paul4fc01e62002-12-13 20:49:00 +0000385 fprintf (stdout,"%% Ambiguous command.\n");
paul718e3742002-12-13 20:15:29 +0000386 break;
387 case CMD_ERR_NO_MATCH:
paul4fc01e62002-12-13 20:49:00 +0000388 fprintf (stdout,"%% Unknown command.\n");
paul718e3742002-12-13 20:15:29 +0000389 break;
390 case CMD_ERR_INCOMPLETE:
paul4fc01e62002-12-13 20:49:00 +0000391 fprintf (stdout,"%% Command incomplete.\n");
paul718e3742002-12-13 20:15:29 +0000392 break;
393 case CMD_SUCCESS_DAEMON:
394 {
395 if (pager && vtysh_pager_name)
396 {
paul4fc01e62002-12-13 20:49:00 +0000397 fp = popen (vtysh_pager_name, "w");
paul718e3742002-12-13 20:15:29 +0000398 if (fp == NULL)
399 {
paula805cc22003-05-01 14:29:48 +0000400 perror ("popen failed for pager");
401 fp = stdout;
paul718e3742002-12-13 20:15:29 +0000402 }
paula805cc22003-05-01 14:29:48 +0000403 else
404 closepager=1;
paul718e3742002-12-13 20:15:29 +0000405 }
406 else
407 fp = stdout;
408
409 if (! strcmp(cmd->string,"configure terminal"))
410 {
411 cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_ZEBRA],
412 line, fp);
413 if (cmd_stat != CMD_WARNING)
414 cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP],
415 line, fp);
416 if (cmd_stat != CMD_WARNING)
417 cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIPNG], line, fp);
418 if (cmd_stat != CMD_WARNING)
419 cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF],
420 line, fp);
421 if (cmd_stat != CMD_WARNING)
422 cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF6], line, fp);
423 if (cmd_stat != CMD_WARNING)
424 cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_BGP],
425 line, fp);
426 if (cmd_stat)
427 {
428 line = "end";
429 vline = cmd_make_strvec (line);
430
431 if (vline == NULL)
432 {
paula805cc22003-05-01 14:29:48 +0000433 if (pager && vtysh_pager_name && fp && closepager)
paul718e3742002-12-13 20:15:29 +0000434 {
435 if (pclose (fp) == -1)
436 {
paula805cc22003-05-01 14:29:48 +0000437 perror ("pclose failed for pager");
paul718e3742002-12-13 20:15:29 +0000438 }
439 fp = NULL;
440 }
441 return;
442 }
443
444 ret = cmd_execute_command (vline, vty, &cmd);
445 cmd_free_strvec (vline);
446 if (ret != CMD_SUCCESS_DAEMON)
447 break;
448 }
449 else
450 if (cmd->func)
451 {
452 (*cmd->func) (cmd, vty, 0, NULL);
453 break;
454 }
455 }
456
457 if (cmd->daemon & VTYSH_ZEBRA)
458 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_ZEBRA], line, fp)
459 != CMD_SUCCESS)
460 break;
461 if (cmd->daemon & VTYSH_RIPD)
462 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP], line, fp)
463 != CMD_SUCCESS)
464 break;
465 if (cmd->daemon & VTYSH_RIPNGD)
466 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIPNG], line, fp)
467 != CMD_SUCCESS)
468 break;
469 if (cmd->daemon & VTYSH_OSPFD)
470 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF], line, fp)
471 != CMD_SUCCESS)
472 break;
473 if (cmd->daemon & VTYSH_OSPF6D)
474 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF6], line, fp)
475 != CMD_SUCCESS)
476 break;
477 if (cmd->daemon & VTYSH_BGPD)
478 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_BGP], line, fp)
479 != CMD_SUCCESS)
480 break;
481 if (cmd->func)
482 (*cmd->func) (cmd, vty, 0, NULL);
483 }
484 }
paula805cc22003-05-01 14:29:48 +0000485 if (pager && vtysh_pager_name && fp && closepager)
paul718e3742002-12-13 20:15:29 +0000486 {
487 if (pclose (fp) == -1)
488 {
paula805cc22003-05-01 14:29:48 +0000489 perror ("pclose failed for pager");
paul718e3742002-12-13 20:15:29 +0000490 }
491 fp = NULL;
492 }
493}
494
495void
496vtysh_execute_no_pager (char *line)
497{
498 vtysh_execute_func (line, 0);
499}
500
501void
502vtysh_execute (char *line)
503{
504 vtysh_execute_func (line, 1);
505}
506
507/* Configration make from file. */
508int
509vtysh_config_from_file (struct vty *vty, FILE *fp)
510{
511 int ret;
512 vector vline;
513 struct cmd_element *cmd;
514
515 while (fgets (vty->buf, VTY_BUFSIZ, fp))
516 {
517 if (vty->buf[0] == '!' || vty->buf[1] == '#')
518 continue;
519
520 vline = cmd_make_strvec (vty->buf);
521
522 /* In case of comment line */
523 if (vline == NULL)
524 continue;
525
526 /* Execute configuration command : this is strict match */
527 ret = cmd_execute_command_strict (vline, vty, &cmd);
528
529 /* Try again with setting node to CONFIG_NODE */
530 if (ret != CMD_SUCCESS
531 && ret != CMD_SUCCESS_DAEMON
532 && ret != CMD_WARNING)
533 {
534 if (vty->node == KEYCHAIN_KEY_NODE)
535 {
536 vty->node = KEYCHAIN_NODE;
537 vtysh_exit_ripd_only ();
538 ret = cmd_execute_command_strict (vline, vty, &cmd);
539
540 if (ret != CMD_SUCCESS
541 && ret != CMD_SUCCESS_DAEMON
542 && ret != CMD_WARNING)
543 {
544 vtysh_exit_ripd_only ();
545 vty->node = CONFIG_NODE;
546 ret = cmd_execute_command_strict (vline, vty, &cmd);
547 }
548 }
549 else
550 {
551 vtysh_execute ("end");
552 vtysh_execute ("configure terminal");
553 vty->node = CONFIG_NODE;
554 ret = cmd_execute_command_strict (vline, vty, &cmd);
555 }
556 }
557
558 cmd_free_strvec (vline);
559
560 switch (ret)
561 {
562 case CMD_WARNING:
563 if (vty->type == VTY_FILE)
paul4fc01e62002-12-13 20:49:00 +0000564 fprintf (stdout,"Warning...\n");
paul718e3742002-12-13 20:15:29 +0000565 break;
566 case CMD_ERR_AMBIGUOUS:
paul4fc01e62002-12-13 20:49:00 +0000567 fprintf (stdout,"%% Ambiguous command.\n");
paul718e3742002-12-13 20:15:29 +0000568 break;
569 case CMD_ERR_NO_MATCH:
paul4fc01e62002-12-13 20:49:00 +0000570 fprintf (stdout,"%% Unknown command: %s", vty->buf);
paul718e3742002-12-13 20:15:29 +0000571 break;
572 case CMD_ERR_INCOMPLETE:
paul4fc01e62002-12-13 20:49:00 +0000573 fprintf (stdout,"%% Command incomplete.\n");
paul718e3742002-12-13 20:15:29 +0000574 break;
575 case CMD_SUCCESS_DAEMON:
576 {
577 if (cmd->daemon & VTYSH_ZEBRA)
578 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_ZEBRA],
579 vty->buf, stdout) != CMD_SUCCESS)
580 break;
581 if (cmd->daemon & VTYSH_RIPD)
582 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP],
583 vty->buf, stdout) != CMD_SUCCESS)
584 break;
585 if (cmd->daemon & VTYSH_RIPNGD)
586 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIPNG],
587 vty->buf, stdout) != CMD_SUCCESS)
588 break;
589 if (cmd->daemon & VTYSH_OSPFD)
590 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF],
591 vty->buf, stdout) != CMD_SUCCESS)
592 break;
593 if (cmd->daemon & VTYSH_OSPF6D)
594 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF6],
595 vty->buf, stdout) != CMD_SUCCESS)
596 break;
597 if (cmd->daemon & VTYSH_BGPD)
598 if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_BGP],
599 vty->buf, stdout) != CMD_SUCCESS)
600 break;
601 if (cmd->func)
602 (*cmd->func) (cmd, vty, 0, NULL);
603 }
604 }
605 }
606 return CMD_SUCCESS;
607}
608
609/* We don't care about the point of the cursor when '?' is typed. */
610int
611vtysh_rl_describe ()
612{
613 int ret;
614 int i;
615 vector vline;
616 vector describe;
617 int width;
618 struct desc *desc;
619
620 vline = cmd_make_strvec (rl_line_buffer);
621
622 /* In case of '> ?'. */
623 if (vline == NULL)
624 {
625 vline = vector_init (1);
626 vector_set (vline, '\0');
627 }
628 else
629 if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
630 vector_set (vline, '\0');
631
632 describe = cmd_describe_command (vline, vty, &ret);
633
paul4fc01e62002-12-13 20:49:00 +0000634 fprintf (stdout,"\n");
paul718e3742002-12-13 20:15:29 +0000635
636 /* Ambiguous and no match error. */
637 switch (ret)
638 {
639 case CMD_ERR_AMBIGUOUS:
640 cmd_free_strvec (vline);
paul4fc01e62002-12-13 20:49:00 +0000641 fprintf (stdout,"%% Ambiguous command.\n");
paul718e3742002-12-13 20:15:29 +0000642 rl_on_new_line ();
643 return 0;
644 break;
645 case CMD_ERR_NO_MATCH:
646 cmd_free_strvec (vline);
paul4fc01e62002-12-13 20:49:00 +0000647 fprintf (stdout,"%% There is no matched command.\n");
paul718e3742002-12-13 20:15:29 +0000648 rl_on_new_line ();
649 return 0;
650 break;
651 }
652
653 /* Get width of command string. */
654 width = 0;
655 for (i = 0; i < vector_max (describe); i++)
656 if ((desc = vector_slot (describe, i)) != NULL)
657 {
658 int len;
659
660 if (desc->cmd[0] == '\0')
661 continue;
662
663 len = strlen (desc->cmd);
664 if (desc->cmd[0] == '.')
665 len--;
666
667 if (width < len)
668 width = len;
669 }
670
671 for (i = 0; i < vector_max (describe); i++)
672 if ((desc = vector_slot (describe, i)) != NULL)
673 {
674 if (desc->cmd[0] == '\0')
675 continue;
676
677 if (! desc->str)
paul4fc01e62002-12-13 20:49:00 +0000678 fprintf (stdout," %-s\n",
paul718e3742002-12-13 20:15:29 +0000679 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd);
680 else
paul4fc01e62002-12-13 20:49:00 +0000681 fprintf (stdout," %-*s %s\n",
paul718e3742002-12-13 20:15:29 +0000682 width,
683 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
684 desc->str);
685 }
686
687 cmd_free_strvec (vline);
688 vector_free (describe);
689
690 rl_on_new_line();
691
692 return 0;
693}
694
695/* result of cmd_complete_command() call will be stored here
696 and used in new_completion() in order to put the space in
697 correct places only */
698int complete_status;
699
700char *
pauldfc0d9b2003-04-18 23:55:29 +0000701command_generator (const char *text, int state)
paul718e3742002-12-13 20:15:29 +0000702{
703 vector vline;
704 static char **matched = NULL;
705 static int index = 0;
706
707 /* First call. */
708 if (! state)
709 {
710 index = 0;
711
712 if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
713 return NULL;
714
715 vline = cmd_make_strvec (rl_line_buffer);
716 if (vline == NULL)
717 return NULL;
718
719 if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
720 vector_set (vline, '\0');
721
722 matched = cmd_complete_command (vline, vty, &complete_status);
723 }
724
725 if (matched && matched[index])
726 return matched[index++];
727
728 return NULL;
729}
730
731char **
732new_completion (char *text, int start, int end)
733{
734 char **matches;
735
pauldfc0d9b2003-04-18 23:55:29 +0000736 matches = rl_completion_matches (text, command_generator);
paul718e3742002-12-13 20:15:29 +0000737
738 if (matches)
739 {
740 rl_point = rl_end;
741 if (complete_status == CMD_COMPLETE_FULL_MATCH)
742 rl_pending_input = ' ';
743 }
744
745 return matches;
746}
747
748char **
749vtysh_completion (char *text, int start, int end)
750{
751 int ret;
752 vector vline;
753 char **matched = NULL;
754
755 if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
756 return NULL;
757
758 vline = cmd_make_strvec (rl_line_buffer);
759 if (vline == NULL)
760 return NULL;
761
762 /* In case of 'help \t'. */
763 if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
764 vector_set (vline, '\0');
765
766 matched = cmd_complete_command (vline, vty, &ret);
767
768 cmd_free_strvec (vline);
769
770 return (char **) matched;
771}
772
773/* BGP node structure. */
774struct cmd_node bgp_node =
775{
776 BGP_NODE,
777 "%s(config-router)# ",
778};
779
780/* BGP node structure. */
781struct cmd_node rip_node =
782{
783 RIP_NODE,
784 "%s(config-router)# ",
785};
786
787struct cmd_node interface_node =
788{
789 INTERFACE_NODE,
790 "%s(config-if)# ",
791};
792
793DEFUNSH (VTYSH_BGPD,
794 router_bgp,
795 router_bgp_cmd,
796 "router bgp <1-65535>",
797 ROUTER_STR
798 BGP_STR
799 AS_STR)
800{
801 vty->node = BGP_NODE;
802 return CMD_SUCCESS;
803}
804
805DEFUNSH (VTYSH_BGPD,
806 address_family_vpnv4,
807 address_family_vpnv4_cmd,
808 "address-family vpnv4",
809 "Enter Address Family command mode\n"
810 "Address family\n")
811{
812 vty->node = BGP_VPNV4_NODE;
813 return CMD_SUCCESS;
814}
815
816DEFUNSH (VTYSH_BGPD,
817 address_family_vpnv4_unicast,
818 address_family_vpnv4_unicast_cmd,
819 "address-family vpnv4 unicast",
820 "Enter Address Family command mode\n"
821 "Address family\n"
822 "Address Family Modifier\n")
823{
824 vty->node = BGP_VPNV4_NODE;
825 return CMD_SUCCESS;
826}
827
828DEFUNSH (VTYSH_BGPD,
829 address_family_ipv4_unicast,
830 address_family_ipv4_unicast_cmd,
831 "address-family ipv4 unicast",
832 "Enter Address Family command mode\n"
833 "Address family\n"
834 "Address Family Modifier\n")
835{
836 vty->node = BGP_IPV4_NODE;
837 return CMD_SUCCESS;
838}
839
840DEFUNSH (VTYSH_BGPD,
841 address_family_ipv4_multicast,
842 address_family_ipv4_multicast_cmd,
843 "address-family ipv4 multicast",
844 "Enter Address Family command mode\n"
845 "Address family\n"
846 "Address Family Modifier\n")
847{
848 vty->node = BGP_IPV4M_NODE;
849 return CMD_SUCCESS;
850}
851
852DEFUNSH (VTYSH_BGPD,
853 address_family_ipv6,
854 address_family_ipv6_cmd,
855 "address-family ipv6",
856 "Enter Address Family command mode\n"
857 "Address family\n")
858{
859 vty->node = BGP_IPV6_NODE;
860 return CMD_SUCCESS;
861}
862
863DEFUNSH (VTYSH_BGPD,
864 address_family_ipv6_unicast,
865 address_family_ipv6_unicast_cmd,
866 "address-family ipv6 unicast",
867 "Enter Address Family command mode\n"
868 "Address family\n"
869 "Address Family Modifier\n")
870{
871 vty->node = BGP_IPV6_NODE;
872 return CMD_SUCCESS;
873}
874
875DEFUNSH (VTYSH_RIPD,
876 key_chain,
877 key_chain_cmd,
878 "key chain WORD",
879 "Authentication key management\n"
880 "Key-chain management\n"
881 "Key-chain name\n")
882{
883 vty->node = KEYCHAIN_NODE;
884 return CMD_SUCCESS;
885}
886
887DEFUNSH (VTYSH_RIPD,
888 key,
889 key_cmd,
890 "key <0-2147483647>",
891 "Configure a key\n"
892 "Key identifier number\n")
893{
894 vty->node = KEYCHAIN_KEY_NODE;
895 return CMD_SUCCESS;
896}
897
898DEFUNSH (VTYSH_RIPD,
899 router_rip,
900 router_rip_cmd,
901 "router rip",
902 ROUTER_STR
903 "RIP")
904{
905 vty->node = RIP_NODE;
906 return CMD_SUCCESS;
907}
908
909DEFUNSH (VTYSH_RIPNGD,
910 router_ripng,
911 router_ripng_cmd,
912 "router ripng",
913 ROUTER_STR
914 "RIPng")
915{
916 vty->node = RIPNG_NODE;
917 return CMD_SUCCESS;
918}
919
920DEFUNSH (VTYSH_OSPFD,
921 router_ospf,
922 router_ospf_cmd,
923 "router ospf",
924 "Enable a routing process\n"
925 "Start OSPF configuration\n")
926{
927 vty->node = OSPF_NODE;
928 return CMD_SUCCESS;
929}
930
931DEFUNSH (VTYSH_OSPF6D,
932 router_ospf6,
933 router_ospf6_cmd,
934 "router ospf6",
935 OSPF6_ROUTER_STR
936 OSPF6_STR)
937{
938 vty->node = OSPF6_NODE;
939 return CMD_SUCCESS;
940}
941
942DEFUNSH (VTYSH_RMAP,
943 route_map,
944 route_map_cmd,
945 "route-map WORD (deny|permit) <1-65535>",
946 "Create route-map or enter route-map command mode\n"
947 "Route map tag\n"
948 "Route map denies set operations\n"
949 "Route map permits set operations\n"
950 "Sequence to insert to/delete from existing route-map entry\n")
951{
952 vty->node = RMAP_NODE;
953 return CMD_SUCCESS;
954}
955
956/* Enable command */
957DEFUNSH (VTYSH_ALL,
958 vtysh_enable,
959 vtysh_enable_cmd,
960 "enable",
961 "Turn on privileged mode command\n")
962{
963 vty->node = ENABLE_NODE;
964 return CMD_SUCCESS;
965}
966
967/* Disable command */
968DEFUNSH (VTYSH_ALL,
969 vtysh_disable,
970 vtysh_disable_cmd,
971 "disable",
972 "Turn off privileged mode command\n")
973{
974 if (vty->node == ENABLE_NODE)
975 vty->node = VIEW_NODE;
976 return CMD_SUCCESS;
977}
978
979/* Configration from terminal */
980DEFUNSH (VTYSH_ALL,
981 vtysh_config_terminal,
982 vtysh_config_terminal_cmd,
983 "configure terminal",
984 "Configuration from vty interface\n"
985 "Configuration terminal\n")
986{
987 vty->node = CONFIG_NODE;
988 return CMD_SUCCESS;
989}
990
991int
992vtysh_exit (struct vty *vty)
993{
994 switch (vty->node)
995 {
996 case VIEW_NODE:
997 case ENABLE_NODE:
998 exit (0);
999 break;
1000 case CONFIG_NODE:
1001 vty->node = ENABLE_NODE;
1002 break;
1003 case INTERFACE_NODE:
1004 case ZEBRA_NODE:
1005 case BGP_NODE:
1006 case RIP_NODE:
1007 case RIPNG_NODE:
1008 case OSPF_NODE:
1009 case OSPF6_NODE:
1010 case MASC_NODE:
1011 case RMAP_NODE:
1012 case VTY_NODE:
1013 case KEYCHAIN_NODE:
1014 vty->node = CONFIG_NODE;
1015 break;
1016 case BGP_VPNV4_NODE:
1017 case BGP_IPV4_NODE:
1018 case BGP_IPV4M_NODE:
1019 case BGP_IPV6_NODE:
1020 vty->node = BGP_NODE;
1021 break;
1022 case KEYCHAIN_KEY_NODE:
1023 vty->node = KEYCHAIN_NODE;
1024 break;
1025 default:
1026 break;
1027 }
1028 return CMD_SUCCESS;
1029}
1030
1031DEFUNSH (VTYSH_ALL,
1032 vtysh_exit_all,
1033 vtysh_exit_all_cmd,
1034 "exit",
1035 "Exit current mode and down to previous mode\n")
1036{
1037 return vtysh_exit (vty);
1038}
1039
1040ALIAS (vtysh_exit_all,
1041 vtysh_quit_all_cmd,
1042 "quit",
1043 "Exit current mode and down to previous mode\n")
1044
1045DEFUNSH (VTYSH_BGPD,
1046 exit_address_family,
1047 exit_address_family_cmd,
1048 "exit-address-family",
1049 "Exit from Address Family configuration mode\n")
1050{
1051 if (vty->node == BGP_IPV4_NODE
1052 || vty->node == BGP_IPV4M_NODE
1053 || vty->node == BGP_VPNV4_NODE
1054 || vty->node == BGP_IPV6_NODE)
1055 vty->node = BGP_NODE;
1056 return CMD_SUCCESS;
1057}
1058
1059DEFUNSH (VTYSH_ZEBRA,
1060 vtysh_exit_zebra,
1061 vtysh_exit_zebra_cmd,
1062 "exit",
1063 "Exit current mode and down to previous mode\n")
1064{
1065 return vtysh_exit (vty);
1066}
1067
1068ALIAS (vtysh_exit_zebra,
1069 vtysh_quit_zebra_cmd,
1070 "quit",
1071 "Exit current mode and down to previous mode\n")
1072
1073DEFUNSH (VTYSH_RIPD,
1074 vtysh_exit_ripd,
1075 vtysh_exit_ripd_cmd,
1076 "exit",
1077 "Exit current mode and down to previous mode\n")
1078{
1079 return vtysh_exit (vty);
1080}
1081
1082ALIAS (vtysh_exit_ripd,
1083 vtysh_quit_ripd_cmd,
1084 "quit",
1085 "Exit current mode and down to previous mode\n")
1086
paul68980082003-03-25 05:07:42 +00001087DEFUNSH (VTYSH_RIPNGD,
1088 vtysh_exit_ripngd,
1089 vtysh_exit_ripngd_cmd,
1090 "exit",
1091 "Exit current mode and down to previous mode\n")
1092{
1093 return vtysh_exit (vty);
1094}
1095
1096ALIAS (vtysh_exit_ripngd,
1097 vtysh_quit_ripngd_cmd,
1098 "quit",
1099 "Exit current mode and down to previous mode\n")
1100
paul718e3742002-12-13 20:15:29 +00001101DEFUNSH (VTYSH_RMAP,
1102 vtysh_exit_rmap,
1103 vtysh_exit_rmap_cmd,
1104 "exit",
1105 "Exit current mode and down to previous mode\n")
1106{
1107 return vtysh_exit (vty);
1108}
1109
1110ALIAS (vtysh_exit_rmap,
1111 vtysh_quit_rmap_cmd,
1112 "quit",
1113 "Exit current mode and down to previous mode\n")
1114
1115DEFUNSH (VTYSH_BGPD,
1116 vtysh_exit_bgpd,
1117 vtysh_exit_bgpd_cmd,
1118 "exit",
1119 "Exit current mode and down to previous mode\n")
1120{
1121 return vtysh_exit (vty);
1122}
1123
1124ALIAS (vtysh_exit_bgpd,
1125 vtysh_quit_bgpd_cmd,
1126 "quit",
1127 "Exit current mode and down to previous mode\n")
1128
1129DEFUNSH (VTYSH_OSPFD,
1130 vtysh_exit_ospfd,
1131 vtysh_exit_ospfd_cmd,
1132 "exit",
1133 "Exit current mode and down to previous mode\n")
1134{
1135 return vtysh_exit (vty);
1136}
1137
1138ALIAS (vtysh_exit_ospfd,
1139 vtysh_quit_ospfd_cmd,
1140 "quit",
1141 "Exit current mode and down to previous mode\n")
1142
paul68980082003-03-25 05:07:42 +00001143DEFUNSH (VTYSH_OSPF6D,
1144 vtysh_exit_ospf6d,
1145 vtysh_exit_ospf6d_cmd,
1146 "exit",
1147 "Exit current mode and down to previous mode\n")
1148{
1149 return vtysh_exit (vty);
1150}
1151
1152ALIAS (vtysh_exit_ospf6d,
1153 vtysh_quit_ospf6d_cmd,
1154 "quit",
1155 "Exit current mode and down to previous mode\n")
1156
1157DEFUNSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D,
paul718e3742002-12-13 20:15:29 +00001158 vtysh_interface,
1159 vtysh_interface_cmd,
1160 "interface IFNAME",
1161 "Select an interface to configure\n"
1162 "Interface's name\n")
1163{
1164 vty->node = INTERFACE_NODE;
1165 return CMD_SUCCESS;
1166}
1167
paul338a9912003-03-01 15:44:10 +00001168DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD,
1169 interface_desc_cmd,
1170 "description .LINE",
1171 "Interface specific description\n"
1172 "Characters describing this interface\n")
paul464dc8d2003-03-28 02:25:45 +00001173
1174DEFSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD,
1175 no_interface_desc_cmd,
1176 "no description",
1177 NO_STR
1178 "Interface specific description\n")
paul338a9912003-03-01 15:44:10 +00001179
paul68980082003-03-25 05:07:42 +00001180DEFUNSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D,
paul718e3742002-12-13 20:15:29 +00001181 vtysh_exit_interface,
1182 vtysh_exit_interface_cmd,
1183 "exit",
1184 "Exit current mode and down to previous mode\n")
1185{
1186 return vtysh_exit (vty);
1187}
1188
1189ALIAS (vtysh_exit_interface,
1190 vtysh_quit_interface_cmd,
1191 "quit",
1192 "Exit current mode and down to previous mode\n")
1193
1194DEFUN (vtysh_write_terminal,
1195 vtysh_write_terminal_cmd,
1196 "write terminal",
1197 "Write running configuration to memory, network, or terminal\n"
1198 "Write to terminal\n")
1199{
1200 int ret;
1201 char line[] = "write terminal\n";
1202 FILE *fp = NULL;
1203
1204 if (vtysh_pager_name)
1205 {
paul4fc01e62002-12-13 20:49:00 +00001206 fp = popen (vtysh_pager_name, "w");
paul718e3742002-12-13 20:15:29 +00001207 if (fp == NULL)
1208 {
1209 perror ("popen");
1210 exit (1);
1211 }
1212 }
1213 else
1214 fp = stdout;
1215
1216 vty_out (vty, "Building configuration...%s", VTY_NEWLINE);
1217 vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
1218 VTY_NEWLINE);
1219
1220 vtysh_config_write (fp);
1221
1222 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_ZEBRA], line);
1223 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_RIP], line);
1224 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_RIPNG], line);
1225 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_OSPF], line);
1226 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_OSPF6], line);
1227 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_BGP], line);
1228
1229 vtysh_config_dump (fp);
1230
1231 if (vtysh_pager_name && fp)
1232 {
1233 fflush (fp);
1234 if (pclose (fp) == -1)
1235 {
1236 perror ("pclose");
1237 exit (1);
1238 }
1239 fp = NULL;
1240 }
1241
1242 return CMD_SUCCESS;
1243}
1244
paul4fc01e62002-12-13 20:49:00 +00001245struct vtysh_writeconfig_t {
1246 int daemon;
1247 int integrated;
1248} vtysh_wc = {-1,0};
1249
1250DEFUN (vtysh_write_config,
1251 vtysh_write_config_cmd,
1252 "write-config (daemon|integrated)",
1253 "Specify config files to write to\n"
1254 "Write per daemon file\n"
1255 "Write integrated file\n"
1256)
1257{
1258 if (!strncmp(argv[0],"d",1)) {
1259 vtysh_wc.daemon = 1;
1260 } else if (!strncmp(argv[0],"i",1)) {
1261 vtysh_wc.integrated = 1;
1262 }
1263 return CMD_SUCCESS;
1264}
1265
1266DEFUN (no_vtysh_write_config,
1267 no_vtysh_write_config_cmd,
1268 "no write-config (daemon|integrated)",
1269 "Negate per daemon and/or integrated config files\n"
1270)
1271{
1272 if (!strncmp(argv[0],"d",1)) {
1273 vtysh_wc.daemon = 0;
1274 } else if (!strncmp(argv[0],"i",1)) {
1275 vtysh_wc.integrated = 0;
1276 }
1277 return CMD_SUCCESS;
1278}
1279
1280int write_config_integrated(void)
paul718e3742002-12-13 20:15:29 +00001281{
1282 int ret;
1283 mode_t old_umask;
1284 char line[] = "write terminal\n";
1285 FILE *fp;
1286 char *integrate_sav = NULL;
1287
1288 /* config files have 0600 perms... */
1289 old_umask = umask (0077);
1290
1291 integrate_sav = malloc (strlen (integrate_default)
1292 + strlen (CONF_BACKUP_EXT) + 1);
1293 strcpy (integrate_sav, integrate_default);
1294 strcat (integrate_sav, CONF_BACKUP_EXT);
1295
1296
paul4fc01e62002-12-13 20:49:00 +00001297 fprintf (stdout,"Building Configuration...\n");
paul718e3742002-12-13 20:15:29 +00001298
1299 /* Move current configuration file to backup config file */
1300 unlink (integrate_sav);
1301 rename (integrate_default, integrate_sav);
paul5087df52003-01-25 06:56:09 +00001302 free (integrate_sav);
paul4fc01e62002-12-13 20:49:00 +00001303
paul718e3742002-12-13 20:15:29 +00001304 fp = fopen (integrate_default, "w");
1305 if (fp == NULL)
1306 {
paul4fc01e62002-12-13 20:49:00 +00001307 fprintf (stdout,"%% Can't open configuration file %s.\n", integrate_default);
paul718e3742002-12-13 20:15:29 +00001308 umask (old_umask);
1309 return CMD_SUCCESS;
1310 }
paul718e3742002-12-13 20:15:29 +00001311
1312 vtysh_config_write (fp);
1313
1314 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_ZEBRA], line);
1315 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_RIP], line);
1316 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_RIPNG], line);
1317 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_OSPF], line);
1318 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_OSPF6], line);
1319 ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_BGP], line);
1320
1321 vtysh_config_dump (fp);
1322
1323 fclose (fp);
1324
paul4fc01e62002-12-13 20:49:00 +00001325 fprintf(stdout,"Integrated configuration saved to %s\n",integrate_default);
1326
1327 fprintf (stdout,"[OK]\n");
1328
paul718e3742002-12-13 20:15:29 +00001329 umask (old_umask);
1330 return CMD_SUCCESS;
1331}
1332
paul4fc01e62002-12-13 20:49:00 +00001333DEFUN (vtysh_write_memory,
1334 vtysh_write_memory_cmd,
1335 "write memory",
1336 "Write running configuration to memory, network, or terminal\n"
1337 "Write configuration to the file (same as write file)\n")
1338{
pauldfc0d9b2003-04-18 23:55:29 +00001339 int ret = CMD_SUCCESS;
paul4fc01e62002-12-13 20:49:00 +00001340 char line[] = "write memory\n";
1341
1342 /* if integrated Zebra.conf explicitely set */
1343 if (vtysh_wc.integrated == 1) {
1344 ret = write_config_integrated();
1345 }
1346
1347 if (!vtysh_wc.daemon) {
1348 return ret;
1349 }
1350
1351 fprintf (stdout,"Building Configuration...\n");
1352
1353 ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_ZEBRA], line, stdout);
1354 ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP], line, stdout);
1355 ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIPNG], line, stdout);
1356 ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF], line, stdout);
1357 ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF6], line, stdout);
1358 ret = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_BGP], line, stdout);
1359
1360 fprintf (stdout,"[OK]\n");
1361
pauldfc0d9b2003-04-18 23:55:29 +00001362 return ret;
paul4fc01e62002-12-13 20:49:00 +00001363}
1364
paul718e3742002-12-13 20:15:29 +00001365ALIAS (vtysh_write_memory,
1366 vtysh_copy_runningconfig_startupconfig_cmd,
1367 "copy running-config startup-config",
1368 "Copy from one file to another\n"
1369 "Copy from current system configuration\n"
1370 "Copy to startup configuration\n")
1371
1372ALIAS (vtysh_write_memory,
1373 vtysh_write_file_cmd,
1374 "write file",
1375 "Write running configuration to memory, network, or terminal\n"
1376 "Write configuration to the file (same as write memory)\n")
1377
1378ALIAS (vtysh_write_terminal,
1379 vtysh_show_running_config_cmd,
1380 "show running-config",
1381 SHOW_STR
1382 "Current operating configuration\n")
1383
1384/* Execute command in child process. */
1385int
1386execute_command (char *command, int argc, char *arg1, char *arg2)
1387{
1388 int ret;
1389 pid_t pid;
1390 int status;
1391
1392 /* Call fork(). */
1393 pid = fork ();
1394
1395 if (pid < 0)
1396 {
1397 /* Failure of fork(). */
1398 fprintf (stderr, "Can't fork: %s\n", strerror (errno));
1399 exit (1);
1400 }
1401 else if (pid == 0)
1402 {
1403 /* This is child process. */
1404 switch (argc)
1405 {
1406 case 0:
1407 ret = execlp (command, command, NULL);
1408 break;
1409 case 1:
1410 ret = execlp (command, command, arg1, NULL);
1411 break;
1412 case 2:
1413 ret = execlp (command, command, arg1, arg2, NULL);
1414 break;
1415 }
1416
1417 /* When execlp suceed, this part is not executed. */
1418 fprintf (stderr, "Can't execute %s: %s\n", command, strerror (errno));
1419 exit (1);
1420 }
1421 else
1422 {
1423 /* This is parent. */
1424 execute_flag = 1;
1425 ret = wait4 (pid, &status, 0, NULL);
1426 execute_flag = 0;
1427 }
1428 return 0;
1429}
1430
1431DEFUN (vtysh_ping,
1432 vtysh_ping_cmd,
1433 "ping WORD",
1434 "send echo messages\n"
1435 "Ping destination address or hostname\n")
1436{
1437 execute_command ("ping", 1, argv[0], NULL);
1438 return CMD_SUCCESS;
1439}
1440
1441DEFUN (vtysh_traceroute,
1442 vtysh_traceroute_cmd,
1443 "traceroute WORD",
1444 "Trace route to destination\n"
1445 "Trace route to destination address or hostname\n")
1446{
1447 execute_command ("traceroute", 1, argv[0], NULL);
1448 return CMD_SUCCESS;
1449}
1450
1451DEFUN (vtysh_telnet,
1452 vtysh_telnet_cmd,
1453 "telnet WORD",
1454 "Open a telnet connection\n"
1455 "IP address or hostname of a remote system\n")
1456{
1457 execute_command ("telnet", 1, argv[0], NULL);
1458 return CMD_SUCCESS;
1459}
1460
1461DEFUN (vtysh_telnet_port,
1462 vtysh_telnet_port_cmd,
1463 "telnet WORD PORT",
1464 "Open a telnet connection\n"
1465 "IP address or hostname of a remote system\n"
1466 "TCP Port number\n")
1467{
1468 execute_command ("telnet", 2, argv[0], argv[1]);
1469 return CMD_SUCCESS;
1470}
1471
paul5087df52003-01-25 06:56:09 +00001472DEFUN (vtysh_ssh,
1473 vtysh_ssh_cmd,
1474 "ssh WORD",
1475 "Open an ssh connection\n"
1476 "[user@]host\n")
1477{
1478 execute_command ("ssh", 1, argv[0], NULL);
1479 return CMD_SUCCESS;
1480}
1481
paul718e3742002-12-13 20:15:29 +00001482DEFUN (vtysh_start_shell,
1483 vtysh_start_shell_cmd,
1484 "start-shell",
1485 "Start UNIX shell\n")
1486{
1487 execute_command ("sh", 0, NULL, NULL);
1488 return CMD_SUCCESS;
1489}
1490
1491DEFUN (vtysh_start_bash,
1492 vtysh_start_bash_cmd,
1493 "start-shell bash",
1494 "Start UNIX shell\n"
1495 "Start bash\n")
1496{
1497 execute_command ("bash", 0, NULL, NULL);
1498 return CMD_SUCCESS;
1499}
1500
1501DEFUN (vtysh_start_zsh,
1502 vtysh_start_zsh_cmd,
1503 "start-shell zsh",
1504 "Start UNIX shell\n"
1505 "Start Z shell\n")
1506{
1507 execute_command ("zsh", 0, NULL, NULL);
1508 return CMD_SUCCESS;
1509}
1510
1511/* Route map node structure. */
1512struct cmd_node rmap_node =
1513{
1514 RMAP_NODE,
1515 "%s(config-route-map)# "
1516};
1517
1518/* Zebra node structure. */
1519struct cmd_node zebra_node =
1520{
1521 ZEBRA_NODE,
1522 "%s(config-router)# "
1523};
1524
1525struct cmd_node bgp_vpnv4_node =
1526{
1527 BGP_VPNV4_NODE,
1528 "%s(config-router-af)# "
1529};
1530
1531struct cmd_node bgp_ipv4_node =
1532{
1533 BGP_IPV4_NODE,
1534 "%s(config-router-af)# "
1535};
1536
1537struct cmd_node bgp_ipv4m_node =
1538{
1539 BGP_IPV4M_NODE,
1540 "%s(config-router-af)# "
1541};
1542
1543struct cmd_node bgp_ipv6_node =
1544{
1545 BGP_IPV6_NODE,
1546 "%s(config-router-af)# "
1547};
1548
1549struct cmd_node ospf_node =
1550{
1551 OSPF_NODE,
1552 "%s(config-router)# "
1553};
1554
1555/* RIPng node structure. */
1556struct cmd_node ripng_node =
1557{
1558 RIPNG_NODE,
1559 "%s(config-router)# "
1560};
1561
1562/* OSPF6 node structure. */
1563struct cmd_node ospf6_node =
1564{
1565 OSPF6_NODE,
1566 "%s(config-ospf6)# "
1567};
1568
1569struct cmd_node keychain_node =
1570{
1571 KEYCHAIN_NODE,
1572 "%s(config-keychain)# "
1573};
1574
1575struct cmd_node keychain_key_node =
1576{
1577 KEYCHAIN_KEY_NODE,
1578 "%s(config-keychain-key)# "
1579};
1580
1581void
1582vtysh_install_default (enum node_type node)
1583{
1584 install_element (node, &config_list_cmd);
1585}
1586
1587/* Making connection to protocol daemon. */
1588int
1589vtysh_connect (struct vtysh_client *vclient, char *path)
1590{
1591 int ret;
1592 int sock, len;
1593 struct sockaddr_un addr;
1594 struct stat s_stat;
1595 uid_t euid;
1596 gid_t egid;
1597
1598 memset (vclient, 0, sizeof (struct vtysh_client));
1599 vclient->fd = -1;
1600
1601 /* Stat socket to see if we have permission to access it. */
1602 euid = geteuid();
1603 egid = getegid();
1604 ret = stat (path, &s_stat);
1605 if (ret < 0 && errno != ENOENT)
1606 {
1607 fprintf (stderr, "vtysh_connect(%s): stat = %s\n",
1608 path, strerror(errno));
1609 exit(1);
1610 }
1611
1612 if (ret >= 0)
1613 {
1614 if (! S_ISSOCK(s_stat.st_mode))
1615 {
1616 fprintf (stderr, "vtysh_connect(%s): Not a socket\n",
1617 path);
1618 exit (1);
1619 }
1620
paul718e3742002-12-13 20:15:29 +00001621 }
1622
1623 sock = socket (AF_UNIX, SOCK_STREAM, 0);
1624 if (sock < 0)
1625 {
1626#ifdef DEBUG
1627 fprintf(stderr, "vtysh_connect(%s): socket = %s\n", path, strerror(errno));
1628#endif /* DEBUG */
1629 return -1;
1630 }
1631
1632 memset (&addr, 0, sizeof (struct sockaddr_un));
1633 addr.sun_family = AF_UNIX;
1634 strncpy (addr.sun_path, path, strlen (path));
1635#ifdef HAVE_SUN_LEN
1636 len = addr.sun_len = SUN_LEN(&addr);
1637#else
1638 len = sizeof (addr.sun_family) + strlen (addr.sun_path);
1639#endif /* HAVE_SUN_LEN */
1640
1641 ret = connect (sock, (struct sockaddr *) &addr, len);
1642 if (ret < 0)
1643 {
1644#ifdef DEBUG
1645 fprintf(stderr, "vtysh_connect(%s): connect = %s\n", path, strerror(errno));
1646#endif /* DEBUG */
1647 close (sock);
1648 return -1;
1649 }
1650 vclient->fd = sock;
1651
1652 return 0;
1653}
1654
1655void
1656vtysh_connect_all()
1657{
1658 /* Clear each daemons client structure. */
paulfe067782003-04-07 16:10:05 +00001659 vtysh_connect (&vtysh_client[VTYSH_INDEX_ZEBRA], ZEBRA_VTYSH_PATH);
1660 vtysh_connect (&vtysh_client[VTYSH_INDEX_RIP], RIP_VTYSH_PATH);
1661 vtysh_connect (&vtysh_client[VTYSH_INDEX_RIPNG], RIPNG_VTYSH_PATH);
1662 vtysh_connect (&vtysh_client[VTYSH_INDEX_OSPF], OSPF_VTYSH_PATH);
1663 vtysh_connect (&vtysh_client[VTYSH_INDEX_OSPF6], OSPF6_VTYSH_PATH);
1664 vtysh_connect (&vtysh_client[VTYSH_INDEX_BGP], BGP_VTYSH_PATH);
paul718e3742002-12-13 20:15:29 +00001665}
1666
1667
1668/* To disable readline's filename completion */
pauldfc0d9b2003-04-18 23:55:29 +00001669char *
1670vtysh_completion_entry_function (const char *ignore, int invoking_key)
paul718e3742002-12-13 20:15:29 +00001671{
pauldfc0d9b2003-04-18 23:55:29 +00001672 return NULL;
paul718e3742002-12-13 20:15:29 +00001673}
1674
1675void
1676vtysh_readline_init ()
1677{
1678 /* readline related settings. */
1679 rl_bind_key ('?', vtysh_rl_describe);
paul68980082003-03-25 05:07:42 +00001680 rl_completion_entry_function = vtysh_completion_entry_function;
paul718e3742002-12-13 20:15:29 +00001681 rl_attempted_completion_function = (CPPFunction *)new_completion;
1682 /* do not append space after completion. It will be appended
1683 in new_completion() function explicitly */
1684 rl_completion_append_character = '\0';
1685}
1686
1687char *
1688vtysh_prompt ()
1689{
1690 struct utsname names;
1691 static char buf[100];
1692 const char*hostname;
1693 extern struct host host;
1694
1695 hostname = host.name;
1696
1697 if (!hostname)
1698 {
1699 uname (&names);
1700 hostname = names.nodename;
1701 }
1702
1703 snprintf (buf, sizeof buf, cmd_prompt (vty->node), hostname);
1704
1705 return buf;
1706}
1707
1708void
1709vtysh_init_vty ()
1710{
1711 /* Make vty structure. */
1712 vty = vty_new ();
1713 vty->type = VTY_SHELL;
1714 vty->node = VIEW_NODE;
1715
1716 /* Initialize commands. */
1717 cmd_init (0);
1718
1719 /* Install nodes. */
1720 install_node (&bgp_node, NULL);
1721 install_node (&rip_node, NULL);
1722 install_node (&interface_node, NULL);
1723 install_node (&rmap_node, NULL);
1724 install_node (&zebra_node, NULL);
1725 install_node (&bgp_vpnv4_node, NULL);
1726 install_node (&bgp_ipv4_node, NULL);
1727 install_node (&bgp_ipv4m_node, NULL);
1728/* #ifdef HAVE_IPV6 */
1729 install_node (&bgp_ipv6_node, NULL);
1730/* #endif */
1731 install_node (&ospf_node, NULL);
1732/* #ifdef HAVE_IPV6 */
1733 install_node (&ripng_node, NULL);
1734 install_node (&ospf6_node, NULL);
1735/* #endif */
1736 install_node (&keychain_node, NULL);
1737 install_node (&keychain_key_node, NULL);
1738
1739 vtysh_install_default (VIEW_NODE);
1740 vtysh_install_default (ENABLE_NODE);
1741 vtysh_install_default (CONFIG_NODE);
1742 vtysh_install_default (BGP_NODE);
1743 vtysh_install_default (RIP_NODE);
1744 vtysh_install_default (INTERFACE_NODE);
1745 vtysh_install_default (RMAP_NODE);
1746 vtysh_install_default (ZEBRA_NODE);
1747 vtysh_install_default (BGP_VPNV4_NODE);
1748 vtysh_install_default (BGP_IPV4_NODE);
1749 vtysh_install_default (BGP_IPV4M_NODE);
1750 vtysh_install_default (BGP_IPV6_NODE);
1751 vtysh_install_default (OSPF_NODE);
1752 vtysh_install_default (RIPNG_NODE);
1753 vtysh_install_default (OSPF6_NODE);
1754 vtysh_install_default (KEYCHAIN_NODE);
1755 vtysh_install_default (KEYCHAIN_KEY_NODE);
1756
1757 install_element (VIEW_NODE, &vtysh_enable_cmd);
1758 install_element (ENABLE_NODE, &vtysh_config_terminal_cmd);
1759 install_element (ENABLE_NODE, &vtysh_disable_cmd);
1760
1761 /* "exit" command. */
1762 install_element (VIEW_NODE, &vtysh_exit_all_cmd);
1763 install_element (VIEW_NODE, &vtysh_quit_all_cmd);
1764 install_element (CONFIG_NODE, &vtysh_exit_all_cmd);
1765 /* install_element (CONFIG_NODE, &vtysh_quit_all_cmd); */
1766 install_element (ENABLE_NODE, &vtysh_exit_all_cmd);
1767 install_element (ENABLE_NODE, &vtysh_quit_all_cmd);
1768 install_element (RIP_NODE, &vtysh_exit_ripd_cmd);
1769 install_element (RIP_NODE, &vtysh_quit_ripd_cmd);
paul68980082003-03-25 05:07:42 +00001770 install_element (RIPNG_NODE, &vtysh_exit_ripngd_cmd);
1771 install_element (RIPNG_NODE, &vtysh_quit_ripngd_cmd);
paul718e3742002-12-13 20:15:29 +00001772 install_element (OSPF_NODE, &vtysh_exit_ospfd_cmd);
1773 install_element (OSPF_NODE, &vtysh_quit_ospfd_cmd);
paul68980082003-03-25 05:07:42 +00001774 install_element (OSPF6_NODE, &vtysh_exit_ospf6d_cmd);
1775 install_element (OSPF6_NODE, &vtysh_quit_ospf6d_cmd);
paul718e3742002-12-13 20:15:29 +00001776 install_element (BGP_NODE, &vtysh_exit_bgpd_cmd);
1777 install_element (BGP_NODE, &vtysh_quit_bgpd_cmd);
1778 install_element (BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd);
1779 install_element (BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd);
1780 install_element (BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd);
1781 install_element (BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd);
1782 install_element (BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd);
1783 install_element (BGP_IPV4M_NODE, &vtysh_quit_bgpd_cmd);
1784 install_element (BGP_IPV6_NODE, &vtysh_exit_bgpd_cmd);
1785 install_element (BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd);
1786 install_element (KEYCHAIN_NODE, &vtysh_exit_ripd_cmd);
1787 install_element (KEYCHAIN_NODE, &vtysh_quit_ripd_cmd);
1788 install_element (KEYCHAIN_KEY_NODE, &vtysh_exit_ripd_cmd);
1789 install_element (KEYCHAIN_KEY_NODE, &vtysh_quit_ripd_cmd);
1790 install_element (RMAP_NODE, &vtysh_exit_rmap_cmd);
1791 install_element (RMAP_NODE, &vtysh_quit_rmap_cmd);
1792
1793 /* "end" command. */
1794 install_element (CONFIG_NODE, &vtysh_end_all_cmd);
1795 install_element (ENABLE_NODE, &vtysh_end_all_cmd);
1796 install_element (RIP_NODE, &vtysh_end_all_cmd);
1797 install_element (RIPNG_NODE, &vtysh_end_all_cmd);
1798 install_element (OSPF_NODE, &vtysh_end_all_cmd);
1799 install_element (OSPF6_NODE, &vtysh_end_all_cmd);
1800 install_element (BGP_NODE, &vtysh_end_all_cmd);
1801 install_element (BGP_IPV4_NODE, &vtysh_end_all_cmd);
1802 install_element (BGP_IPV4M_NODE, &vtysh_end_all_cmd);
1803 install_element (BGP_VPNV4_NODE, &vtysh_end_all_cmd);
1804 install_element (BGP_IPV6_NODE, &vtysh_end_all_cmd);
1805 install_element (KEYCHAIN_NODE, &vtysh_end_all_cmd);
1806 install_element (KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
1807 install_element (RMAP_NODE, &vtysh_end_all_cmd);
1808
paul338a9912003-03-01 15:44:10 +00001809 install_element (INTERFACE_NODE, &interface_desc_cmd);
paul464dc8d2003-03-28 02:25:45 +00001810 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
paul718e3742002-12-13 20:15:29 +00001811 install_element (INTERFACE_NODE, &vtysh_end_all_cmd);
1812 install_element (INTERFACE_NODE, &vtysh_exit_interface_cmd);
1813 install_element (INTERFACE_NODE, &vtysh_quit_interface_cmd);
1814 install_element (CONFIG_NODE, &router_rip_cmd);
1815#ifdef HAVE_IPV6
1816 install_element (CONFIG_NODE, &router_ripng_cmd);
1817#endif
1818 install_element (CONFIG_NODE, &router_ospf_cmd);
1819#ifdef HAVE_IPV6
1820 install_element (CONFIG_NODE, &router_ospf6_cmd);
1821#endif
1822 install_element (CONFIG_NODE, &router_bgp_cmd);
1823 install_element (BGP_NODE, &address_family_vpnv4_cmd);
1824 install_element (BGP_NODE, &address_family_vpnv4_unicast_cmd);
1825 install_element (BGP_NODE, &address_family_ipv4_unicast_cmd);
1826 install_element (BGP_NODE, &address_family_ipv4_multicast_cmd);
1827#ifdef HAVE_IPV6
1828 install_element (BGP_NODE, &address_family_ipv6_cmd);
1829 install_element (BGP_NODE, &address_family_ipv6_unicast_cmd);
1830#endif
1831 install_element (BGP_VPNV4_NODE, &exit_address_family_cmd);
1832 install_element (BGP_IPV4_NODE, &exit_address_family_cmd);
1833 install_element (BGP_IPV4M_NODE, &exit_address_family_cmd);
1834 install_element (BGP_IPV6_NODE, &exit_address_family_cmd);
1835 install_element (CONFIG_NODE, &key_chain_cmd);
1836 install_element (CONFIG_NODE, &route_map_cmd);
1837 install_element (KEYCHAIN_NODE, &key_cmd);
1838 install_element (KEYCHAIN_NODE, &key_chain_cmd);
1839 install_element (KEYCHAIN_KEY_NODE, &key_chain_cmd);
1840 install_element (CONFIG_NODE, &vtysh_interface_cmd);
1841 install_element (ENABLE_NODE, &vtysh_show_running_config_cmd);
1842 install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd);
1843 install_element (ENABLE_NODE, &vtysh_write_file_cmd);
1844
1845 /* write terminal command */
1846 install_element (ENABLE_NODE, &vtysh_write_terminal_cmd);
1847 install_element (CONFIG_NODE, &vtysh_write_terminal_cmd);
1848 install_element (BGP_NODE, &vtysh_write_terminal_cmd);
1849 install_element (BGP_VPNV4_NODE, &vtysh_write_terminal_cmd);
1850 install_element (BGP_IPV4_NODE, &vtysh_write_terminal_cmd);
1851 install_element (BGP_IPV4M_NODE, &vtysh_write_terminal_cmd);
1852 install_element (BGP_IPV6_NODE, &vtysh_write_terminal_cmd);
1853 install_element (RIP_NODE, &vtysh_write_terminal_cmd);
1854 install_element (RIPNG_NODE, &vtysh_write_terminal_cmd);
1855 install_element (OSPF_NODE, &vtysh_write_terminal_cmd);
1856 install_element (OSPF6_NODE, &vtysh_write_terminal_cmd);
1857 install_element (INTERFACE_NODE, &vtysh_write_terminal_cmd);
1858 install_element (RMAP_NODE, &vtysh_write_terminal_cmd);
1859 install_element (KEYCHAIN_NODE, &vtysh_write_terminal_cmd);
1860 install_element (KEYCHAIN_KEY_NODE, &vtysh_write_terminal_cmd);
1861
1862 /* write memory command */
1863 install_element (ENABLE_NODE, &vtysh_write_memory_cmd);
1864 install_element (CONFIG_NODE, &vtysh_write_memory_cmd);
1865 install_element (BGP_NODE, &vtysh_write_memory_cmd);
1866 install_element (BGP_VPNV4_NODE, &vtysh_write_memory_cmd);
1867 install_element (BGP_IPV4_NODE, &vtysh_write_memory_cmd);
1868 install_element (BGP_IPV4M_NODE, &vtysh_write_memory_cmd);
1869 install_element (BGP_IPV6_NODE, &vtysh_write_memory_cmd);
1870 install_element (RIP_NODE, &vtysh_write_memory_cmd);
1871 install_element (RIPNG_NODE, &vtysh_write_memory_cmd);
1872 install_element (OSPF_NODE, &vtysh_write_memory_cmd);
1873 install_element (OSPF6_NODE, &vtysh_write_memory_cmd);
1874 install_element (INTERFACE_NODE, &vtysh_write_memory_cmd);
1875 install_element (RMAP_NODE, &vtysh_write_memory_cmd);
1876 install_element (KEYCHAIN_NODE, &vtysh_write_memory_cmd);
1877 install_element (KEYCHAIN_KEY_NODE, &vtysh_write_memory_cmd);
1878
1879 install_element (VIEW_NODE, &vtysh_ping_cmd);
1880 install_element (VIEW_NODE, &vtysh_traceroute_cmd);
1881 install_element (VIEW_NODE, &vtysh_telnet_cmd);
1882 install_element (VIEW_NODE, &vtysh_telnet_port_cmd);
paul5087df52003-01-25 06:56:09 +00001883 install_element (VIEW_NODE, &vtysh_ssh_cmd);
paul718e3742002-12-13 20:15:29 +00001884 install_element (ENABLE_NODE, &vtysh_ping_cmd);
1885 install_element (ENABLE_NODE, &vtysh_traceroute_cmd);
1886 install_element (ENABLE_NODE, &vtysh_telnet_cmd);
1887 install_element (ENABLE_NODE, &vtysh_telnet_port_cmd);
1888 install_element (ENABLE_NODE, &vtysh_start_shell_cmd);
1889 install_element (ENABLE_NODE, &vtysh_start_bash_cmd);
1890 install_element (ENABLE_NODE, &vtysh_start_zsh_cmd);
1891
paul718e3742002-12-13 20:15:29 +00001892 install_element (CONFIG_NODE, &vtysh_log_stdout_cmd);
1893 install_element (CONFIG_NODE, &no_vtysh_log_stdout_cmd);
1894 install_element (CONFIG_NODE, &vtysh_log_file_cmd);
1895 install_element (CONFIG_NODE, &no_vtysh_log_file_cmd);
1896 install_element (CONFIG_NODE, &vtysh_log_syslog_cmd);
1897 install_element (CONFIG_NODE, &no_vtysh_log_syslog_cmd);
1898 install_element (CONFIG_NODE, &vtysh_log_trap_cmd);
1899 install_element (CONFIG_NODE, &no_vtysh_log_trap_cmd);
1900 install_element (CONFIG_NODE, &vtysh_log_record_priority_cmd);
1901 install_element (CONFIG_NODE, &no_vtysh_log_record_priority_cmd);
paul4fc01e62002-12-13 20:49:00 +00001902 install_element (CONFIG_NODE, &vtysh_write_config_cmd);
1903 install_element (CONFIG_NODE, &no_vtysh_write_config_cmd);
paul718e3742002-12-13 20:15:29 +00001904}